设计模式——门面模式 | 外观模式
哈喽,各位盆友们!我是你们亲爱的学徒小z,今天给大家分享的文章是设计模式的——门面模式。
文章目录
- 定义
- 通用类图
- 1.通用结构
- 2.优点
- 3.缺点
- 使用场景
- 注意事项
- 1.一个子系统可以有多个门面
- 2.门面不参与子系统内的业务逻辑
定义
-
定义:要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行。门面模式提供一个高层次的接口,使得子系统更易于使用。
隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口。这种类型的设计模式属于结构型模式,它向现有的系统添加一个接口,来隐藏系统的复杂性
通用类图

1.通用结构
-
Facade门面角色
客户端可以调用这个角色的方法。此角色知晓子系统的所有功能和责任。一般情况下, 本角色会将所有从客户端发来的请求委派到相应的子系统去,也就说该角色没有实际的业务逻辑,只是一个委托类。
-
subsystem子系统角色
可以同时有一个或者多个子系统。每一个子系统都不是一个单独的类,而是一个类的集合。子系统并不知道门面的存在。对于子系统而言,门面仅仅是另外一个客户端而已。
-
通用代码
//子系统 public class ClassA {public void doSomethingA(){//业务逻辑} } public class ClassB {public void doSomethingB(){//业务逻辑} } public class ClassC {public void doSomethingC(){//业务逻辑} }//门面对象 public class Facade {//被委托的对象private ClassA a = new ClassA();private ClassB b = new ClassB();private ClassC c = new ClassC();//提供给外部访问的方法public void methodA(){this.a.doSomethingA();}public void methodB(){this.b.doSomethingB();}public void methodC(){this.c.doSomethingC();} }
2.优点
- 减少系统之间的相互依赖:客户端与子系统之间的依赖减少
- 提高了灵活性
- 提高了安全性
3.缺点
- 违反了开闭原则:对子系统的修改可能需要对门面类进行相应的修改
使用场景
- 为一个复杂的模块或子系统提供一个供外界访问的接口
- 子系统相对独立——外界对子系统的访问只要黑箱操作即可
注意事项
1.一个子系统可以有多个门面
-
适用条件
-
门面已经庞大到不能忍受的程度
-
子系统可以提供不同访问路径
以门面模式的通用源代码为例。ClassA、ClassB、ClassC是一个子系统的中3个对象,现在有两个不同的高层模块来访问该子系统,模块一可以完整的访问所有业务逻辑,也就是通用代码中的Facade类,它是子系统的信任模块;而模块二属于受限访问对象,只能访问methodB方法。
处理方法:需要建立两个门面以供不同的高层模块来访问,在原有的通用源码上增加一个新的门面
//新增门面 public class Facade2 {//引用原有的门面private Facade facade = new Facade();//对外提供唯一的访问子系统的方法public void methodB(){this.facade.methodB();} }
增加的门面非常简单,委托给了已经存在的门面对象Facade进行处理,为什么要使用委 托而不再编写一个委托到子系统的方法呢?那是因为在面向对象的编程中,尽量保持相同的 代码只编写一遍,避免以后到处修改相似代码出现问题
2.门面不参与子系统内的业务逻辑
举例说明
我们把门面上的methodC上的逻辑修改一下,它必须先调用ClassA的doSomethingA方法,然后再调用ClassC的doSomethingC方法
//修改门面
public class Facade {//被委托的对象private ClassA a = new ClassA();private ClassB b = new ClassB();private ClassC c = new ClassC();//提供给外部访问的方法public void methodA(){this.a.doSomethingA();}public void methodB(){this.b.doSomethingB();}public void methodC(){this.a.doSomethingA();this.c.doSomethingC();}
}
这样的设计不靠谱。因为已经让门面对象参与了业务逻辑,门 面对象只是提供一个访问子系统的一个路径而已,它不应该也不能参与具体的业务逻辑,否则就会产生一个倒依赖的问题:子系统必须依赖门面才能被访问,这是设计上一个严重错误,不仅违反了单一职责原则,同时也破坏了系统的封装性
解决方法
-
建立一个封装类,封装完毕后提供给门面对象
//封装类 public class Context {//委托处理private ClassA a = new ClassA();private ClassC c = new ClassC();//复杂的计算public void complexMethod(){this.a.doSomethingA();this.c.doSomethingC();} }//门面类 public class Facade {//被委托的对象private ClassA a = new ClassA();private ClassB b = new ClassB();private Context context = new Context();//提供给外部访问的方法public void methodA(){this.a.doSomethingA();}public void methodB(){this.b.doSomethingB();}public void methodC(){this.context.complexMethod();} }
-
该封装类的作用就是产生一个业务规则complexMethod,并且它的生存环境是在子系统内,仅仅依赖两个相关的对象,门面对象通过对它的访问完成一个复杂的业务逻辑
-
通过这样一次封装后,门面对象又不参与业务逻辑了,在门面模式中,门面角色应该是稳定,它不应该经常变化,一个系统一旦投入运行它就不应该被改变,因为它是一个系统对外的接口。
相关文章:

设计模式——门面模式 | 外观模式
哈喽,各位盆友们!我是你们亲爱的学徒小z,今天给大家分享的文章是设计模式的——门面模式。 文章目录 定义通用类图1.通用结构2.优点3.缺点 使用场景注意事项1.一个子系统可以有多个门面2.门面不参与子系统内的业务逻辑 定义 定义:…...
FPGA时序分析和约束学习笔记(1、FPGA基本原理)
FPGA时序分析和约束学习笔记-(1、FPGA基本原理) Field现场Programmable可编程Gate门Array阵列 1、FPGA基本资源组成 可编程逻辑功能块(logic elements ,缩写LE) 片内互联线(interconnect,缩写…...

VMware桥接模式无法连接网络
windows下打开控制面板,找到WLAN,记住下面的名称(带有VMware的都是虚拟机的网卡,要找到物理主机的网卡) 回到VMware,编辑——打开虚拟网络编辑器 桥接选择上面的WLAN下的网络名称,确定即可。&…...

YOLO11改进|卷积篇|引入空间通道重组卷积ScConv
目录 一、【SCConv】卷积1.1【SCConv】卷积介绍1.2【SCConv】核心代码 二、添加【SCConv】卷积2.1STEP12.2STEP22.3STEP32.4STEP4 三、yaml文件与运行3.1yaml文件3.2运行成功截图 一、【SCConv】卷积 1.1【SCConv】卷积介绍 SCConv 模块提供了一种新的视角来看待CNNs的特征提取…...

Java:方法详解
目录 一.什么是方法(method) 二.方法定义 三.方法中实参和形参的关系 四.方法重载 五.递归 一.什么是方法(method) 方法就是一个代码片段,再C语言中我们曾经学过一个类似的方式——函数,他们都是将具有独立功能的代码组织成一个整体,形成…...
Python 三方库下载安装
Python 三方库下载安装 1、在线安装 pip install pandas # 直接安装 python -m pip install pandas # 使用指定Python中的pip进行安装 pip install pandas1.2.3 # 安装指定版本 pip install pandas -i http://pypi.douban.com/simple --trusted-host pypi.…...

使用npm i报错node-sass失败问题解决
node 版本:v14.15.4 解决方法: npm config set sass_binary_sitehttps://npmmirror.com/mirrors/node-sass设置完之后,再npm i 就可以下载成功 亲测有效...
vite+vue3实现动态路径导入
最近在做一个项目有个需求: 项目图片分为英语,中文,德语 ,我将这些图片存放到/image/language/下面的每个语言的文件夹内,如en,zh-cn文件夹下面存放对应的语言的图片,如果在代码里面写路径的话,除了要写一堆路径还要判断不同的语言,非常麻烦,但是在vue3vite里面import导入的是加…...

JAVA——File类
目录 1.概述 2.构造方法 a.根据文件路径创建文件对象 b.根据父级路径和子级路径创建对象 c.根据File表示的路径和String表示路径进行拼接 3.常见方法 a.判断文件是否存在 b.判断文件是否为文件夹 c.判断是否为文件 d.获取文件大小 e.获取文件的绝对路径 f.获取定义…...

掌握Postman,开启API测试新纪元!
Postman是一款流行的API测试工具和开发环境,旨在简化API开发过程、测试和文档编制。它提供了一套功能强大的工具,帮助开发人员更轻松地构建、测试和调试Web服务。 Postman 工具的优势 Postman 可以快速构建请求、还可以保存以后再使用。 Postman 还提…...

JAVA-数据结构-排序
1.直接插入排序 1.原理:和玩扑克牌一样,从左边第二个牌开始,选中这个,和前面的所有牌比较,插在合适的位置 public static void insertsort(int[] arr){//直接插入排序for (int i 1; i < arr.length; i) {//此循环…...

初识数据结构--时间复杂度 和 空间复杂度
数据结构前言 数据结构 数据结构是计算机存储、组织数据的方式(指不仅能存储数据,还能够管理数据-->增删改)。指相互之间存在一种或多种特定关系的数据元素的集合。没有单一的数据结构对所有用途都有用,所以我们要学习各种的数据结构,比…...

Ubuntu QT 交叉编译环境搭建
文章目录 下载安装qtCreatornot a valid identifier 的错误 安装g下载并安装交叉编译器下载交叉编译器安装交叉编译器 下载编译 ARM 的Qt平台源码配置arm的QT平台 下载安装qtCreator 去QT下载官网下载对应需要的QT软件。 这里下载5.12.96版本的 改变安装包权限,…...
C语言中缓冲区底层实现以及数据输入的处理
C语言中缓冲区底层实现以及数据输入的处理 一、缓冲区的概念 在C语言的标准输入输出操作中,缓冲区(Buffer) 扮演着至关重要的角色。在计算机系统中,缓冲区是一块用于暂存数据的内存区域。在输入输出(I/O)…...
RocketMQ事务消息原理
一、RocketMQ事务消息原理: RocketMQ 在 4.3 版本之后实现了完整的事务消息,基于MQ的分布式事务方案,本质上是对本地消息表的一个封装,整体流程与本地消息表一致,唯一不同的就是将本地消息表存在了MQ内部&…...

【Java】IntelliJ IDEA开发环境安装
一、下载 官方地址:https://www.jetbrains.com/idea/ 点击Download直接下载 二、安装 双击安装包,点击Next 选择安装路径,点击Next 勾选安装内容 安装完成。 三、创建项目 打开IDEA,填写项目名称,选择项目安装路径…...
Go语言中的通道 (Channel) 实践:Goroutine之间的通信
1. 引言 在Go语言中,并发编程是其核心优势之一。与其他编程语言不同,Go语言推荐使用通道 (Channel) 来进行多线程或并发任务的协调与通信,而非使用锁机制。本文将介绍如何通过通道在多个goroutine之间进行通信,避免竞争条件和复杂…...

常用类(二)--String类的简单总结
文章目录 1.基本介绍1.1创建对象1.2找到对应下标的字符1.3找到对应字符的下标1.4指定位置开始遍历1.5反向进行遍历1.6大小写之间的转换1.7字符串转换为数组1.8元素的替换1.9字符串的分割1.10字符串的截取 2.StringBuilder和StringBuffer2.1 StringBuilder的引入2.2面试题目 1.基…...
Spring Boot开发:从入门到精通
Spring Boot开发:从入门到精通 当你在开发一个新的Java应用时,是否曾经感到苦恼于繁琐的配置和重复的代码?Spring Boot就像一位友好的助手,向你伸出援手,让开发变得轻松愉快。从这一单一框架中,你可以快速…...
《数据结构》--队列【各种实现,算法推荐】
一、认识队列 队列是一种常见的数据结构,按照先进先出(FIFO,First In First Out)的原则排列数据。也就是说,最早进入队列的元素最先被移除。队列主要支持两种基本操作: 入队(enqueue࿰…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...

定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...
06 Deep learning神经网络编程基础 激活函数 --吴恩达
深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...
什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南
文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果
AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机
这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机,因为在使用过程中发现 Airsim 对外部监控相机的描述模糊,而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置,最后在源码示例中找到了,所以感…...

c++第七天 继承与派生2
这一篇文章主要内容是 派生类构造函数与析构函数 在派生类中重写基类成员 以及多继承 第一部分:派生类构造函数与析构函数 当创建一个派生类对象时,基类成员是如何初始化的? 1.当派生类对象创建的时候,基类成员的初始化顺序 …...

Java数组Arrays操作全攻略
Arrays类的概述 Java中的Arrays类位于java.util包中,提供了一系列静态方法用于操作数组(如排序、搜索、填充、比较等)。这些方法适用于基本类型数组和对象数组。 常用成员方法及代码示例 排序(sort) 对数组进行升序…...
拟合问题处理
在机器学习中,核心任务通常围绕模型训练和性能提升展开,但你提到的 “优化训练数据解决过拟合” 和 “提升泛化性能解决欠拟合” 需要结合更准确的概念进行梳理。以下是对机器学习核心任务的系统复习和修正: 一、机器学习的核心任务框架 机…...