结构型设计模式(一):门面模式 组合模式

门面模式 Facade

1、什么是门面模式

门面模式(Facade Pattern)是一种结构型设计模式,旨在为系统提供一个统一的接口,以便于访问子系统中的一群接口。它通过定义一个高层接口,简化了客户端与子系统之间的交互,从而降低了系统的复杂性。

2、为什么使用门面模式

  1. 简化接口:门面模式通过定义一个高层接口,简化了客户端与子系统之间的交互,使得客户端无需直接与子系统的复杂接口打交道。
  2. 解耦客户端和子系统:通过引入门面,客户端与子系统的依赖关系得到解耦,客户端只需与门面进行交互,而不需要关心子系统的具体实现。
  3. 提高可维护性:门面模式将子系统的实现细节封装起来,有助于提高系统的可维护性,降低了系统的复杂性。

3、如何实现门面模式

设计实现一个简单的计算启动过程

// 子系统 - CPU
class CPU {
    public void start() {
        System.out.println("CPU is starting...");
    }
}

// 子系统 - Memory
class Memory {
    public void load() {
        System.out.println("Memory is loading...");
    }
}

// 子系统 - HardDrive
class HardDrive {
    public void read() {
        System.out.println("HardDrive is reading...");
    }
}

// 门面类 - ComputerFacade
class ComputerFacade {
    private CPU cpu;
    private Memory memory;
    private HardDrive hardDrive;

    public ComputerFacade() {
        this.cpu = new CPU();
        this.memory = new Memory();
        this.hardDrive = new HardDrive();
    }

    public void startComputer() {
        cpu.start();
        memory.load();
        hardDrive.read();
        System.out.println("Computer is started and ready to use.");
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        ComputerFacade computerFacade = new ComputerFacade();
        computerFacade.startComputer();
    }
}

4、是否存在缺陷和不足

  1. 不符合开闭原则:当系统中的子系统发生变化时,可能需要修改门面类,不符合开闭原则。
  2. 可能导致过多门面类:随着系统的不断扩展,可能会出现多个门面类,导致系统变得复杂。

5、如何缓解缺陷和不足

  1. 使用配置文件:将子系统的配置信息放置在配置文件中,通过读取配置文件的方式动态创建门面类,提高系统的灵活性。
  2. 使用抽象工厂模式:可以结合抽象工厂模式,将门面的创建过程交给工厂类,从而降低客户端与门面的耦合度。
// 抽象产品 - CPU
interface CPU {
    void start();
}

// 具体产品A - ConcreteCPUA
class ConcreteCPUA implements CPU {
    @Override
    public void start() {
        System.out.println("ConcreteCPUA is starting...");
    }
}

// 具体产品B - ConcreteCPUB
class ConcreteCPUB implements CPU {
    @Override
    public void start() {
        System.out.println("ConcreteCPUB is starting...");
    }
}

// 抽象产品 - Memory
interface Memory {
    void load();
}

// 具体产品A - ConcreteMemoryA
class ConcreteMemoryA implements Memory {
    @Override
    public void load() {
        System.out.println("ConcreteMemoryA is loading...");
    }
}

// 具体产品B - ConcreteMemoryB
class ConcreteMemoryB implements Memory {
    @Override
    public void load() {
        System.out.println("ConcreteMemoryB is loading...");
    }
}

// 抽象产品 - HardDrive
interface HardDrive {
    void read();
}

// 具体产品A - ConcreteHardDriveA
class ConcreteHardDriveA implements HardDrive {
    @Override
    public void read() {
        System.out.println("ConcreteHardDriveA is reading...");
    }
}

// 具体产品B - ConcreteHardDriveB
class ConcreteHardDriveB implements HardDrive {
    @Override
    public void read() {
        System.out.println("ConcreteHardDriveB is reading...");
    }
}

// 抽象工厂接口
interface ComputerFactory {
    CPU createCPU();
    Memory createMemory();
    HardDrive createHardDrive();
}

// 具体工厂A
class ConcreteFactoryA implements ComputerFactory {
    @Override
    public CPU createCPU() {
        return new ConcreteCPUA();
    }

    @Override
    public Memory createMemory() {
        return new ConcreteMemoryA();
    }

    @Override
    public HardDrive createHardDrive() {
        return new ConcreteHardDriveA();
    }
}

// 具体工厂B
class ConcreteFactoryB implements ComputerFactory {
    @Override
    public CPU createCPU() {
        return new ConcreteCPUB();
    }

    @Override
    public Memory createMemory() {
        return new ConcreteMemoryB();
    }

    @Override
    public HardDrive createHardDrive() {
        return new ConcreteHardDriveB();
    }
}

// 门面类
class ComputerFacade {
    private CPU cpu;
    private Memory memory;
    private HardDrive hardDrive;

    public ComputerFacade(ComputerFactory factory) {
        this.cpu = factory.createCPU();
        this.memory = factory.createMemory();
        this.hardDrive = factory.createHardDrive();
    }

    public void startComputer() {
        cpu.start();
        memory.load();
        hardDrive.read();
        System.out.println("Computer is started and ready to use.");
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        // 使用工厂A创建电脑
        ComputerFactory factoryA = new ConcreteFactoryA();
        ComputerFacade computerFacadeA = new ComputerFacade(factoryA);
        computerFacadeA.startComputer();

        // 使用工厂B创建电脑
        ComputerFactory factoryB = new ConcreteFactoryB();
        ComputerFacade computerFacadeB = new ComputerFacade(factoryB);
        computerFacadeB.startComputer();
    }
}

上面这个例子中,抽象工厂模式用于创建不同系列的电脑产品,而门面类的创建过程交给工厂类,客户端代码通过选择不同的工厂来创建不同系列的电脑,无需关心具体产品的创建过程,有助于提高系统的灵活性和可维护性

组合模式 Composite

1、什么是组合模式

组合模式通过将对象组织成树形结构来表示整体-部分层次结构,使得客户端可以统一对待单个对象和对象的组合。它主要包含三个角色:叶子节点(Leaf)、组合节点(Composite)、客户端(Client)。

2、为什么使用组合模式

  1. 统一接口:组合模式使得客户端可以统一对待单个对象和对象的组合,因为它们共享相同的接口。
  2. 灵活性:客户端无需关心对象是叶子节点还是组合节点,可以在不同层次构建复杂的对象结构。
  3. 简化客户端代码:客户端无需判断操作的是单个对象还是对象组合,简化了客户端代码。

3、如何使用组合模式

设计实现一个文件系统

import java.util.ArrayList;
import java.util.List;

// 抽象组件 - 文件和目录的共同接口
interface FileSystemComponent {
    void display();
}

// 叶子节点 - 文件
class FileLeaf implements FileSystemComponent {
    private String name;

    public FileLeaf(String name) {
        this.name = name;
    }

    @Override
    public void display() {
        System.out.println("File: " + name);
    }
}

// 组合节点 - 目录
class DirectoryComposite implements FileSystemComponent {
    private String name;
    private List<FileSystemComponent> components;

    public DirectoryComposite(String name) {
        this.name = name;
        this.components = new ArrayList<>();
    }

    public void addComponent(FileSystemComponent component) {
        components.add(component);
    }

    public void removeComponent(FileSystemComponent component) {
        components.remove(component);
    }

    @Override
    public void display() {
        System.out.println("Directory: " + name);
        for (FileSystemComponent component : components) {
            component.display();
        }
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        // 构建文件系统结构
        FileSystemComponent file1 = new FileLeaf("file1.txt");
        FileSystemComponent file2 = new FileLeaf("file2.txt");

        DirectoryComposite dir1 = new DirectoryComposite("Folder 1");
        dir1.addComponent(file1);
        dir1.addComponent(file2);

        FileSystemComponent file3 = new FileLeaf("file3.txt");
        DirectoryComposite dir2 = new DirectoryComposite("Folder 2");
        dir2.addComponent(file3);
        dir2.addComponent(dir1);

        // 显示文件系统结构
        dir2.display();
    }
}

4、是否存在缺陷和不足

  1. 限制类型一致性:组合模式要求所有组件都实现相同的接口,这可能限制了组件的类型一致性。
  2. 不支持单个对象的特殊处理:组合模式统一对待单个对象和组合对象,因此可能无法支持对单个对象的特殊处理。

5、如何缓解缺陷和不足

  1. 使用抽象构件类:引入一个抽象构建类,包含所有子类共有的方法,从而提高组件的类型一致性。
  2. 在叶子节点实现特殊处理:在叶子节点类中实现特殊处理逻辑,以满足对单个对象的特殊需求。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/252197.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于Java SSM框架实现图书店仓库进销存管理系统项目【项目源码+论文说明】

基于java的SSM框架实现图书店仓库进销存管理系统演示 摘要 仓库作为储存货物的核心功能之一&#xff0c;在整个仓储中具有非常重要的作用&#xff0c;是社会物质生产的必要条件。良好的仓库布局环境能够对货物进入下一个环节前的质量起保证作用&#xff0c;能够为货物进入市场…

FPGA设计与实战之时钟及时序简介1

文章目录 一、时钟定义二、基本时序三、总结一、时钟定义 我们目前设计的电路以同步时序电路为主,时钟做为电路工作的基准而显得非常重要。 简单的接口电路比如I2C、SPI等,复杂一点接口比如Ethernet的MII、GMII等接口,它们都有一个或多个时钟信号。 那么什么是时钟信号?它…

PADS9.5 : 原图绘图图纸尺寸下修改

原图绘图图纸尺寸下修改 图页边界线也要修改 如果二者选择不一致&#xff1a; 会出现下图所示情况&#xff1a;

Android hwcomposer服务启动流程

Android hwcomposer服务启动流程 客户端 binder远程调用 服务端 surfaceflinger --binder--> hwcomposer .hal文件编译时生成支持binder进程间远程调用通信的cpp文件 在out/soong/.intermediates/hardware/interfaces/graphics/composer/2.1/ 目录下找…

基于VGG-16+Android+Python的智能车辆驾驶行为分析—深度学习算法应用(含全部工程源码)+数据集+模型(三)

目录 前言总体设计系统整体结构图系统流程图 运行环境模块实现1. 数据预处理2. 模型构建3. 模型训练及保存1&#xff09;模型训练2&#xff09;模型保存 4. 模型生成1&#xff09;模型导入及调用2&#xff09;相关代码&#xff08;1&#xff09;布局文件&#xff08;2&#xff…

LCR 120. 寻找文件副本

解题思路&#xff1a; 利用增强for循环遍历documents&#xff0c;将遇见的id加入hmap中&#xff0c;如果id在hamp中存在&#xff0c;则直接返回id class Solution {public int findRepeatDocument(int[] documents) {Set<Integer> hmapnew HashSet<>();for(int d…

插入排序----希尔排序

希尔排序 希尔排序法又称缩小增量法。希尔排序法的基本思想是&#xff1a;先选定一个整数&#xff0c;把待排序文件中所有记录分成个gap组&#xff0c;所有距离为的记录分在同一组内&#xff0c;并对每一组内的记录进行排序。然后&#xff0c;取&#xff0c;重复上述分组和排序…

千亿露酒市场的未来之“露”

执笔 | 尼 奥 编辑 | 扬 灵 12月15日&#xff0c;以“以美为酿&#xff0c;品致未来”为主题的中国露酒产业发展大会暨露酒价值论坛在“中国酒都”宜宾举办。 近年来&#xff0c;露酒产业发展异军突起&#xff0c;市场销售规模超越黄酒、葡萄酒品类&#xff0c;成为中国酒…

【Qt QML 入门】TextEdit

TextEdit可以显示多行可编辑的格式化文。默认是无边框的&#xff0c;可以和父控件完美融合。 import QtQuick import QtQuick.Window import QtQuick.ControlsWindow {id: winwidth: 800height: 600visible: trueTextEdit {id: textEditanchors.centerIn: parenttext: "He…

Sentinel使用详解

组件简介 Sentinel是阿里开源的一套用于服务容错的综合性解决方案。它以流量为切入点&#xff0c;从流量控制、熔断降级、系统负载保护等多个维度来保护服务的稳定性。Sentinel承接了阿里巴巴近10年的双十一大促流量的核心场景&#xff0c;例如秒杀、消息削峰填谷、集群流量控…

翻译: LLM工具使用和代理Tool use and agents

欢迎来到本周的最后一个视频。在这个视频中&#xff0c;我想与您分享LLM&#xff08;大型语言模型&#xff09;开始能够使用工具的情况&#xff0c;以及讨论一下前沿的“代理”主题&#xff0c;这是让LLM自己决定下一步采取什么行动的领域。让我们来看看。在早期的食物订单接收…

操作系统期末复习-内存管理

一、内存管理 分页存储管理&#xff0c;是将一个进程的逻辑地址空间分成若干个大小相等的片&#xff0c;称为页面或页&#xff0c;并为各页加以编号&#xff0c;从0开始&#xff0c;如第0页、第1页等。相应地&#xff0c;也把内存空间分成与页面相同大小的若干个存储块&#xf…

人工智能文本分类

在本文中&#xff0c;我们全面探讨了文本分类技术的发展历程、基本原理、关键技术、深度学习的应用&#xff0c;以及从RNN到Transformer的技术演进。文章详细介绍了各种模型的原理和实战应用&#xff0c;旨在提供对文本分类技术深入理解的全面视角。 一、引言 文本分类作为人工…

交叉熵在机器学习里做损失的意义

交叉熵是机器学习中常用的损失函数之一&#xff0c;特别适用于分类任务。其背后的核心思想是衡量两个概率分布之间的差异。在分类问题中&#xff0c;通常有一个真实分布&#xff08;ground truth distribution&#xff09;和一个模型预测的分布&#xff08;predicted distribut…

knime 安装Regex Extractor节点

1、在File中&#xff0c;找到install knime extensions 2、接着输入palladian&#xff0c;然后选择select all&#xff0c;最后点击next就可以了&#xff0c;等待安装就可以了 3、然后重启knime就可以看到了Regex Extractor节点

整理了上百个开源中文大语言模型,涵盖模型、应用、数据集、微调、部署、评测

自ChatGPT为代表的大语言模型&#xff08;Large Language Model, LLM&#xff09;出现以后&#xff0c;由于其惊人的类通用人工智能&#xff08;AGI&#xff09;的能力&#xff0c;掀起了新一轮自然语言处理领域的研究和应用的浪潮。 尤其是以ChatGLM、LLaMA等平民玩家都能跑起…

PADS9.5 : 原理图电源网络 和 地网 络添加

原理图电源网络 和 地网 络添加 添加电源网络 1、点击连线 2、2、连线 3、3、连线时&#xff0c;右键 4、4、点击电源&#xff0c;因为该网络已经有3.3v&#xff0c;它会弹出网络确认&#xff0c;确定即可&#xff0c;如果 需要其他电源网络&#xff0c;双击即可修改 5、双击…

Impala4.x源码阅读笔记(一)——HdfsTextScanner解析

前言 本文为笔者个人阅读Apache Impala源码时的笔记&#xff0c;仅代表我个人对代码的理解&#xff0c;个人水平有限&#xff0c;文章可能存在理解错误、遗漏或者过时之处。如果有任何错误或者有更好的见解&#xff0c;欢迎指正。 在文章Impala3.4源码阅读笔记&#xff08;七…