结构型设计模式之外观模式【设计模式系列】

系列文章目录

C++技能系列
Linux通信架构系列
C++高性能优化编程系列
深入理解软件架构设计系列
高级C++并发线程编程
设计模式系列

期待你的关注哦!!!
在这里插入图片描述

现在的一切都是为将来的梦想编织翅膀,让梦想在现实中展翅高飞。
Now everything is for the future of dream weaving wings, let the dream fly in reality.

结构型设计模式之外观模式

  • 系列文章目录
  • 一、外观模式介绍
  • 二、外观模式优缺点
    • 2.1 优点
    • 2.2 缺点
  • 三、外观模式使用场景
  • 四、外观模式实现
  • 五、外观模式应用实例

一、外观模式介绍

⚠️ 意图:
为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。

⚠️ 主要解决:
降低访问复杂系统的内部子系统时的复杂度,简化客户端之间的接口。

⚠️ 何时使用:
1、客户端不需要知道系统内部的复杂联系,整个系统只需提供一个"接待员"即可。 2、定义系统的入口

⚠️ 如何解决:
客户端不与系统耦合,外观类与系统耦合。

在这里插入图片描述

图1_1 外观模式类图

(1)外观模式符合是“迪米特法则”,通过引入一个新的外观类可以降低原有系统的复杂度,外观类充当了客户类与子系统类之间的“第三者”,同时降低客户类与子系统类的耦合度。外观模式就是实现代码重构以便达到“迪米特法则”要求的一个强有力的武器。

(2)外观模式要求一个子系统的外部与其内部的通信通过一个统一的外观对象进行,外观类将客户端与子系统的内部复杂性分隔开,使得客户端只需要与外观对象打交道,而不需要与子系统内部的很多对象打交道。

(3)外观模式从很大程度上提高了客户端使用的便捷性,使得客户端无须关心子系统的工作细节,通过外观角色即可调用相关功能。

(4)不要试图通过外观类为子系统增加新行为 ,不要通过继承一个外观类在子系统中加入新的行为,这种做法是错误的。外观模式的用意是为子系统提供一个集中化和简化的沟通渠道,而不是向子系统加入新的行为,新的行为的增加应该通过修改原有子系统类或增加新的子系统类来实现,不能通过外观类来实现。

(5)在外观模式中,通常只需要一个外观类,并且此外观类只有一个实例。在很多情况下为了节约系统资源,一般将外观类设计为单例类。当然并不意味着在整个系统里只能有一个外观类,在一个系统中可以设计多个外观类,每个外观类都负责和一些特定的子系统交互,向用户提供相应的业务功能。

(6)当增加新的子系统或者移除子系统时需要修改外观类,可以通过引入抽象外观类在一定程度上解决该问题,客户端针对抽象外观类进行编程。对于新的业务需求,不修改原有外观类,而对应增加一个新的具体外观类,由新的具体外观类来关联新的子系统对象,同时通过修改配置文件来达到不修改源代码并更换外观类的目的。

二、外观模式优缺点

2.1 优点

  • 对客户屏蔽子系统组件,减少了客户处理的对象数目并使得子系统使用起来更加容易。通过引入外观模式,客户代码将变得很简单,与之关联的对象也很少。

  • 实现了子系统与客户之间的松耦合关系,使得子系统的组件变化不会影响到调用它的客户类,只需要调整外观类即可。

  • 降低了大型软件系统中的编译依赖性,并简化了系统在不同平台之间的移植过程,因为编译一个子系统一般不需要编译所有其他的子系统。一个子系统的修改对其他子系统没有任何影响,而且子系统内部变化也不会影响到外观对象。

  • 只是提供了一个访问子系统的统一入口,并不影响用户直接使用子系统类。

2.2 缺点

  • 不能很好地限制客户使用子系统类,如果对客户访问子系统类做太多的限制则减少了可变性和灵活性。

  • 在不引入抽象外观类的情况下,增加新的子系统可能需要修改外观类或客户端的源代码,违背了“开闭原则”。

三、外观模式使用场景

  • 当要为一个复杂子系统提供一个简单接口时。子系统往往因为不断演化而变得越来越复杂。大多数模式使用时都会产生更多更小的类,使得子系统更具可重用性,也更容易对子系统进行定制,但也给那些不需要定制子系统的用户带来一些使用上的困难。facade可以提供一个简单的缺省视图,视图对大多数用户来说已经足够,而那些需要更多的可定制性的用户可以越过facade层。

  • 客户程序与抽象类的实现部分之间存在着很大的依赖性。引入 facade将这个子系统与客户以及其他的子系统分离,可以提高子系统的独立性 和可移植性。

  • 当你需要构建一个层次结构的子系统时,使用 facade模式定义子系统中每层的入口点。如果子系统之间是相互依赖的,你可以让它们仅通过facade进行通讯,从而简化了它们之间的依赖关系。

适配器模式和外观模式共同点是将不好用的几口适配成好用的接口。但是适配器模式是将一个接口通过适配来间接转换为另一个接口,外观模式主要是提供一个整洁的一致的接口给客户端。

抽象工厂模式可以与外观模式一起使用以提供一个接口,用来以一种子系统独立的方式创建子系统对象。

中介者模式与外观模式抽象了一些已有的类的功能。中介者模式的目的是对同事之间的任意通讯进行抽象,通常集中不属于任何单个对象的功能。中介者模式的同事对象知道中介者并与中介者通信,而不是直接与其他同类对象通信。外观模式仅对子系统对象的接口进行抽象,从而使子系统的接口更容易使用;外观模式并不定义新功能,子系统也不知道Facade的存在。

一般仅需要一个Facade对象,因此Facade对象通常属于Singleton模式。

四、外观模式实现

Facade外观类:

#ifndef FACADE_H
#define FACADE_H
#include <iostream>
#include "SubSystemA.h"
#include "SubSystemB.h"class Facade
{
public:Facade(){m_pSubSystemA = new SubSystemA();m_pSubSystemB = new SubSystemB();}~Facade(){delete m_pSubSystemA;delete m_pSubSystemB;m_pSubSystemA = NULL;m_pSubSystemB = NULL;}void operationWrapper(){m_pSubSystemA->operation();m_pSubSystemB->operation();}
private:SubSystemA* m_pSubSystemA;SubSystemB* m_pSubSystemB;
};#endif // FACADE_H

SubSystemA子系统类:

#ifndef SUBSYSTEMA_H
#define SUBSYSTEMA_H
#include <iostream>class SubSystemA
{
public:SubSystemA(){}~SubSystemA(){}void operation(){std::cout << "SubSystemA::operation" << std::endl;}
};#endif // SUBSYSTEMA_H

SubSystemB子系统类:

#ifndef SUBSYSTEMB_H
#define SUBSYSTEMB_H
#include <iostream>class SubSystemB
{
public:SubSystemB(){}~SubSystemB(){}void operation(){std::cout << "SubSystemB::operation" << std::endl;}
};#endif // SUBSYSTEMB_H

客户调用程序:

#include "Facade.h"int main()
{Facade* facade = new Facade();facade->operationWrapper();return 0;
}

五、外观模式应用实例

假设编译一个程序需要经过四个步骤:词法分析、语法分析、中间代码生成、机器码生成。对于编译器系统,可以使用外观模式,定义一个高层接口Compiler类,Compiler有一个名为compile的函数。客户只需调用compile函数就可以编译程序,compile函数内部的具体操作,客户无需知道。

#include <iostream>using namespace std;//subsystem
class Scanner
{
public:void scan(){cout << "scanning..." << endl;}
};class Parser
{
public:void parse(){cout << "parsing..." << endl;}
};class GenMidCoder
{
public:void generateCode(){cout << "generating middle code...." << endl;}
};class GenMachineCoder
{
public:void generateCode(){cout << "generating machine code...." << endl;}
};//Facade
class Compiler
{
public:void compile(){Scanner sanner;Parser parser;GenMidCoder genMidCoder;GenMachineCoder genMachineCoder;sanner.scan();parser.parse();genMidCoder.generateCode();genMachineCoder.generateCode();}
};int main()
{Compiler compiler;compiler.compile();return 0;
}

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

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

相关文章

剑指YOLOv8改进最新MPDIoU损失函数:超越现有多种G/D/C/EIoU,23年7月首发论文,高效准确的边界框回归的损失

💡本篇内容:剑指YOLOv8改进最新MPDIoU损失函数:超越现有多种G/D/C/EIoU,23年7月首发论文,高效准确的边界框回归的损失 💡🚀🚀🚀本博客 改进源代码改进 适用于 YOLOv8 按步骤操作运行改进后的代码即可 💡:重点:该专栏《剑指YOLOv8原创改进》只更新改进 YOLO…

雷达信号处理自学总结(持续更新)

傅里叶变换的频率分辨率 频率分辨率 采样频率 信号长度 频率分辨率 \frac{采样频率 }{信号长度} 频率分辨率信号长度采样频率​ 可用numpy模块的fft.fftfreq函数求出傅里叶变换的频率分辨率。 https://numpy.org/doc/stable/reference/generated/numpy.fft.fftfreq.html

若依vue -【 44】

44 服务监控讲解 1 需求 显示CPU、内存、服务器信息、Java虚拟机信息、磁盘状态的信息 2 前端 RuoYi-Vue\ruoyi-ui\src\views\monitor\server\index.vue <script> import { getServer } from "/api/monitor/server";export default {name: "Server&quo…

JS(es6)同时给多个变量赋值

在ES6中&#xff0c;可以使用解构赋值语法同时给多个变量赋值。解构赋值语法可以从数组或对象中提取值&#xff0c;并将其赋给多个变量。 1. 数组解构赋值&#xff1a; const [var1, var2, var3] [1, 2, 3] console.log(var1); // 输出 1 console.log(var2); // 输出 2 cons…

前端技术搭建(动态图片)拖拽拼图!!(内含实现原理)

文章目录 前端技术搭建&#xff08;动态图片&#xff09;拖拽拼图(内含实现原理)导言功能介绍效果演示链接&#xff08;觉得不错的&#xff0c;请一键三连嘤嘤嘤&#xff09;项目目录页面搭建css样式设置工具函数游戏实现逻辑 开源地址总结 前端技术搭建&#xff08;动态图片&a…

什么是tcp rst以及什么时候产生?

rst包是仅在header control bits设置rst的空payload包&#xff0c;用于强制关闭tcp连接。常在以下场景发送 远程主机没有监听该端口 远程主机强迫关闭了一个现有连接。比如服务端进程崩溃后重启会向之前连接发送rst 相比于四次挥手的fin&#xff0c;rst是在异常情况下的无条…

SpringBoot整合JavaMail

SpringBoot整合JavaMail 简单使用-发送简单邮件 介绍协议 导入坐标 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId></dependency>添加配置 spring:mail:host: smtp.qq.co…

企业邮箱搭建费用,smtp邮件系统怎么搭建?验证码邮件群发,有哪些推荐邮件群发系统?

您是否为没法发smtp群发邮件而苦恼&#xff0c;别担心&#xff0c;这里将给大家介绍一下什么是企业邮箱&#xff0c;邮局系统怎么搭建&#xff0c;验证码邮件群发&#xff0c;有哪些推荐邮件群发系统&#xff1f; 企业邮箱搭建&#xff1a;成本和考量因素 在如今数字化的商业…

Wonderful Sql

Wonderful Sql 一. 初识数据库 练习题 1.1 编写一条 CREATE TABLE 语句&#xff0c;用来创建一个包含表 1-A 中所列各项的表 Addressbook &#xff08;地址簿&#xff09;&#xff0c;并为 regist_no &#xff08;注册编号&#xff09;列设置主键约束 表1-A 表 Addressbook…

java代码审计6之ssrf

文章目录 1、java支持的网络请求协议&#xff1a;2、Java 中能发起⽹络请求的类2.1、仅⽀持 HTTP/HTTPS 协议的类2.2、⽀持 sun.net.www.protocol 所有协议的类2.3、审计关键词 3、靶场3.1、漏洞代码13.2、ftp协议读取技巧3.3、无回显之探测内网3.4、无回显之探测文件 之前的文…

el-input 文本框 输入数字校验

目录 1. 输入整数 2. 输入整数和小数 3. 输入两位小数 1. 输入整数 <el-inputv-model"scopeRows.row.inWarehouseRow.Quantity"type"number"blur"getRowData(scopeRows.row.inWarehouseRow)"oninput"valuevalue.replace(/^0|[^0-9]/g…

【前缀和】238. 除自身以外数组的乘积

238. 除自身以外数组的乘积 解题思路 前缀与后缀的思路对于给定索引i&#xff0c;将它左边的所有数字乘积乘以右边所有数字的乘积初始化两个数组L R计算L[i] L[i - 1] * nums[i - 1] 也就是左侧所有数字的乘积计算R[i] R[i 1] * nums[i 1] 也就是右侧所有数字的成绩计算L…

Ceph概述、准备ceph部署环境、cephadm概述、安装Ceph集群、ceph块存储、存储池、rbd镜像管理、ceph客户端配置

day03 day03ceph概述部署Ceph节点准备cephadm准备基础环境安装ceph实现块存储块存储基础存储池镜像ceph客户端 ceph概述 ceph可以实现的存储方式&#xff1a; 块存储&#xff1a;提供像普通硬盘一样的存储&#xff0c;为使用者提供“硬盘”文件系统存储&#xff1a;类似于NFS…

cst 导出z方向电场分布图的后处理方式(matlab origin)?

文章目录 一、使用Matlab进行后处理&#xff1a;二、使用Origin进行后处理 当我们使用Matlab或Origin对CST导出的Z方向电场分布图进行后处理时&#xff0c;可以这样做&#xff1a; 一、使用Matlab进行后处理&#xff1a; 1. 导入数据&#xff1a; 使用Matlab的文件读取函数&am…

【数据分析专栏之Python篇】二、Jupyer Notebook安装配置及基本使用

文章目录 前言一、Jupter Notebook是什么1.1 简介1.2 组成部分1.3 Jupyter Notebook的主要特点 二、为什么使用Jupyter Notebook?三、安装四、Jupyter Notebok配置4.1 基本配置4.2 配置开机自启与后台运行4.3 开启代码自动补全 五、两种键盘输入模式5.1 编辑模式5.2 命令模式5…

13.python设计模式【策略者模式】

内容&#xff1a;定义一系列的算法&#xff0c;把它们一个一个的封装起来&#xff0c;并且使它们可以相互替换。本模式使得算法可独立于使用它的客户而变化。角色&#xff1a; 抽象策略&#xff08;Strategy&#xff09;具体策略&#xff08;ConcreteStrategy&#xff09;上下文…

探究Spring Bean的六种作用域:了解适用场景和使用方式

这里写目录标题 单例&#xff08;Singleton&#xff09;作用域&#xff1a;原型&#xff08;Prototype&#xff09;作用域&#xff1a;请求&#xff08;Request&#xff09;作用域&#xff1a;会话&#xff08;Session&#xff09;作用域&#xff1a;全局&#xff08;applicati…

【vue3+ts】TypeError: Cannot read properties of undefined (reading ‘commit‘)

项目场景&#xff1a; <script lang"ts"> import { defineComponent, reactive, ref } from vue import { useStore } from vuex export default defineComponent({name: Login.vue,components: {},setup () {const onFormSubmit (result: boolean) > {if…

http 请求报文响应报文的格式以及Token cookie session 区别

面试必备 http 请求报文响应报文的格式Token cookie session 区别 http 请求报文响应报文的格式 HTTP 请求报文和响应报文的格式如下&#xff1a; HTTP 请求报文格式&#xff1a; <方法> <路径> <协议版本> <请求头部字段1>: <值1> <请求头…

4-Linux组管理和权限管理

Linux组管理和权限管理 Linux组的基本介绍文件/目录的所有者组的创建文件/目录所在的组其它组改变用户所在的组权限的基本介绍第0-9位说明rwx权限详解rwx 修饰文件时rwx修饰目录时 修改权限第一种方式&#xff1a;、-、 变更权限第二种方式&#xff1a;通过数字变更权限 修改文…