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

门面模式 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 {@Overridepublic void start() {System.out.println("ConcreteCPUA is starting...");}
}// 具体产品B - ConcreteCPUB
class ConcreteCPUB implements CPU {@Overridepublic void start() {System.out.println("ConcreteCPUB is starting...");}
}// 抽象产品 - Memory
interface Memory {void load();
}// 具体产品A - ConcreteMemoryA
class ConcreteMemoryA implements Memory {@Overridepublic void load() {System.out.println("ConcreteMemoryA is loading...");}
}// 具体产品B - ConcreteMemoryB
class ConcreteMemoryB implements Memory {@Overridepublic void load() {System.out.println("ConcreteMemoryB is loading...");}
}// 抽象产品 - HardDrive
interface HardDrive {void read();
}// 具体产品A - ConcreteHardDriveA
class ConcreteHardDriveA implements HardDrive {@Overridepublic void read() {System.out.println("ConcreteHardDriveA is reading...");}
}// 具体产品B - ConcreteHardDriveB
class ConcreteHardDriveB implements HardDrive {@Overridepublic void read() {System.out.println("ConcreteHardDriveB is reading...");}
}// 抽象工厂接口
interface ComputerFactory {CPU createCPU();Memory createMemory();HardDrive createHardDrive();
}// 具体工厂A
class ConcreteFactoryA implements ComputerFactory {@Overridepublic CPU createCPU() {return new ConcreteCPUA();}@Overridepublic Memory createMemory() {return new ConcreteMemoryA();}@Overridepublic HardDrive createHardDrive() {return new ConcreteHardDriveA();}
}// 具体工厂B
class ConcreteFactoryB implements ComputerFactory {@Overridepublic CPU createCPU() {return new ConcreteCPUB();}@Overridepublic Memory createMemory() {return new ConcreteMemoryB();}@Overridepublic 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;}@Overridepublic 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);}@Overridepublic 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. 在叶子节点实现特殊处理:在叶子节点类中实现特殊处理逻辑,以满足对单个对象的特殊需求。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

优质全套SpringMVC教程

三、SpringMVC 在SSM整合中&#xff0c;MyBatis担任的角色是持久层框架&#xff0c;它能帮我们访问数据库&#xff0c;操作数据库 Spring能利用它的两大核心IOC、AOP整合框架 1、SpringMVC简介 1.1、什么是MVC MVC是一种软件架构的思想&#xff08;不是设计模式-思想就是我们…

Java 中使用装饰器模式 wrapped 一个不能被重写的父类中的接口方法

在开发中&#xff0c;有时候使用第三方框架时&#xff0c;我们因为特殊需求&#xff0c;需要继承框架中的一个Java类重写它的某个方法来达到期望的目的。 如果需要被重写的方法被使用 final 修饰了&#xff0c;这种情况下我们是无法直接继承这个类来重写这个方法的。 本文所述…

16 Vue3中的refs引用

概述 In Vue, refs are references to DOM elements or other component instances that have been mounted to the DOM. 在 Vue 中&#xff0c;Refs 是对 DOM 元素或已安装到 DOM 的其他组件实例的引用。 One of the major use cases for refs is direct DOM manipulation …

【具身智能评估3】具身视觉语言规划(EVLP)度量标准汇总

参考论文&#xff1a;Core Challenges in Embodied Vision-Language Planning 论文作者&#xff1a;Jonathan Francis, Nariaki Kitamura, Felix Labelle, Xiaopeng Lu, Ingrid Navarro, Jean Oh 论文原文&#xff1a;https://arxiv.org/abs/2106.13948 论文出处&#xff1a;Jo…

netty-daxin-4(httpwebsocket)

文章目录 学习链接http服务端NettyHttpServerHelloWorldServerHandler 客户端ApiPost websocket初步了解为什么需要 WebSocket简介 浏览器的WebSocket客户端客户端的简单示例客户端的 APIWebSocket 构造函数webSocket.readyStatewebSocket.onopenwebSocket.onclosewebSocket.ο…

Unity 使用AddRelativeForce方法给刚体施加力详解

之前我们总结过使用AddForce方法给刚体施加力&#xff1a;Unity 使用AddForce方法给刚体施加力详解-CSDN博客 本文总结另外一个方法AddRelativeForce&#xff0c;本质上它们区别不大&#xff0c;都是给刚体施加一个持续的力&#xff0c;唯一区别就是施加力时候使用的坐标系不一…

MATLAB - MPC - QP Solvers

系列文章目录 前言 模型预测控制器 QP 求解器将线性 MPC 优化问题转换为一般形式的 QP 问题 受到线性不等式约束 其中 x 是解向量。H 是黑森矩阵。当预测模型和调整权重在运行时不发生变化时&#xff0c;该矩阵保持不变。A 是线性约束系数矩阵。当预测模型在运行时不发生变化时…

Eclipse 自动生成注解,如果是IDEA可以参考编译器自带模版进行修改

IDEA添加自动注解 左上角选择 File -> Settings -> Editor -> File and Code Templates&#xff1b; 1、添加class文件自动注解&#xff1a; ​/*** <b>Function: </b> todo* program: ${NAME}* Package: ${PACKAGE_NAME}* author: Jerry* date: ${YEA…

介绍strncpy函数

strncpy函数需要引用#include <string.h>头文件 函数原型&#xff1a; char *_Dest 是字符串的去向 char *_Source是字符串的来源 size_t_Count是复制字符串的大小 #include <stdio.h> #include <string.h> int main() { char arr[128] { \0 }; …

【JAVA-Day69】抛出异常的精髓:深度解析 throw、throws 关键字,优雅处理异常问题

抛出异常的精髓&#xff1a;深度解析 throw、throws 关键字&#xff0c;优雅处理异常问题 &#x1f680; 抛出异常的精髓&#xff1a;深度解析 throw、throws 关键字&#xff0c;优雅处理异常问题 &#x1f680;一、什么是抛出异常 &#x1f60a;二、如何抛出异常 &#x1f914…

什么是计算机网络?计算机网络基础知识

1.网络的组成部分&#xff1a;由主机&#xff0c;路由器&#xff0c;交换机等组成 2.网络结构&#xff1a;网络的网络 3.信息交换方式&#xff1a;电路交换和分组交换 4.网络分层&#xff1a;分清职责&#xff0c;物理层&#xff0c;链路层&#xff0c;网络层&#xff0c;运…

IDEA中如何使用Vue

一、在IDEA中安装Vue插件 1.先点击File-->Settings-->Plugins 2.点击进去后在Marketplace下的搜索框搜索Vue.js插件进行下载&#xff0c;下载完后点击Install 3.上一步操作进行完后&#xff0c;点击Installed在其搜索框下搜索Vue插件并且进行勾选&#xff0c;勾选后点…

0x23 剪枝

0x23 剪枝 剪枝&#xff0c;就是减少搜索树规模&#xff0c;尽早排除搜索树中不必要的分支的一种手段。形象地看&#xff0c;就好像剪掉了搜索树的枝条&#xff0c;故被称为“剪枝”。在深度优先搜索中&#xff0c;有以下几类常见的剪枝方法&#xff1a; 1.优化搜索顺序 在一…

MetaAI语音翻译大模型Seamless登场,主打AI无缝同声传译

论文题目&#xff1a; Seamless: Multilingual Expressive and Streaming Speech Translation 论文链接&#xff1a; https://ai.meta.com/research/publications/seamless-multilingual-expressive-and-streaming-speech-translation/ 代码链接&#xff1a; GitHub - facebook…

DSP捕获输入简单笔记

之前使用stm32的大概原理是&#xff1a; 输入引脚输入一个脉冲&#xff0c;捕获1开始极性捕获&#xff0c;捕获的是从启动捕获功能开始计数&#xff0c;捕获的是当前的计数值&#xff1b; 例如一个脉冲&#xff0c;捕获1捕获上升沿&#xff0c;捕获2捕获下降沿&#xff1b;而两…

爬虫工作量由小到大的思维转变---<第十二章 Scrapy之sql存储与爬虫高效性的平衡艺术>

前言: (本文仅属于技术性探讨,不属于教文) 刚好&#xff0c;前阵子团队还在闲聊这个问题呢。你知道吗&#xff0c;在数据收集这个行当里&#xff0c;怎么存数据这问题就跟“先有鸡还是先有蓝”一样&#xff0c;没完没了的循环往复。老规矩&#xff0c;咱们先搞清楚我们的“鸡…

reactive数据不响应

我们知道&#xff0c;reactive函数用于创建对象等复杂数据的响应式代理对象&#xff0c;当该对象的属性发生变化时&#xff0c;会自动触发视图更新。 但在Vue 3中&#xff0c;当我们使用reactive创建的对象或数组进行赋值时&#xff0c;尽管能够完成正常的赋值操作&#xff0c…

Linux 系统开机启动流程

可能没有完全理解&#xff0c;后期整理完Linux的内容&#xff0c;应该理解会深入一些&#xff0c;试着用更简洁的方式和图形来记录&#xff0c;以及一些概念的完善 2023-12-14 一、开机流程 BIOS MBR/GPT 加载 BIOS 的硬件信息与进行自检&#xff0c;并依据设定取得第一个可…

TrustZone之调试、跟踪和分析

接下来,我们将查看系统中的调试和跟踪组件,如下图所示: 现代Arm系统包括支持调试和性能分析的广泛功能。在TrustZone中,我们必须确保这些功能不能被用来危害系统的安全性。 关于调试功能,考虑开发新的SoC。不同的开发人员被信任调试系统的不同部分。芯片公司的工程…

第十九章 : Spring Boot 集成RabbitMQ(三)

第十九章 : Spring Boot 集成RabbitMQ(三) 前言 本章节重点:RabbitMQ消息确认机制的代码示例:生产者消息确认机制、Return消息机制、消费端ACK和Nack机制3种消息确认模式。 Springboot 版本 2.3.2.RELEASE ,RabbitMQ 3.9.11,Erlang 24.2消息确认的场景 使用RabbitMQ很…