C++设计模式——Facade外观模式

一,外观模式简介

外观模式是一种结构型设计模式, 又称为门面模式,也是一种基于创建对象来实现的模式,为子系统中的各组接口的使用提供了统一的访问入口。

外观模式对外提供了一个对象,让外部客户端(Client)对子系统的访问都是基于该对象来完成,这个对象被称为外观对象(Facade Object),外观对象为子系统的访问提供了一个简单而且统一的入口。

客户端只需要关注Facade提供的对外接口的用法,而不需要关注子系统之间的复杂交互等细节。

举个例子,用户在电话购物的时候,可以不需要知道货物的流动和仓库处理等细节,只需要拨电话然后下单。

二,外观模式的结构

外观对象(Facade):它的底层封装了系统的各个子模块,向用户屏蔽了底层的复杂结构,在内部调用各种子系统的函数,对外提供一些简化的接口。

子系统对象(SubSystem):是组成复杂系统的各个独立模块,它们各自实现特定的功能,然后被Facade统一调用。

对应UML类图:

代码实现:

#include <iostream>
#include <vector>using namespace std;class SubSystem {
public:virtual void operation() = 0;
};class SubSystem_A: public SubSystem{
public:void operation_A() {cout << "Exec operation_A from SubSystem_A" << endl;}void operation() override {operation_A();}
};class SubSystem_B: public SubSystem{
public:void operation_B() {cout << "Exec operation_B from SubSystem_B" << endl;}void operation() override {operation_B();}
};class SubSystem_C: public SubSystem{
public:void operation_C() {cout << "Exec operation_C from SubSystem_C" << endl;}void operation() override {operation_C();}
};class Facade {
private:std::vector<SubSystem*> subsystems;
public:Facade() {subsystems.push_back(new SubSystem_A);subsystems.push_back(new SubSystem_B);subsystems.push_back(new SubSystem_C);}~Facade() {for (auto* subsystem : subsystems) {delete subsystem;}}void executeOperations() {for (auto& subsystem : subsystems) {subsystem->operation();}}
};int main() {Facade facade;facade.executeOperations();return 0;
}

运行结果:

Exec operation_A from SubSystem_A
Exec operation_B from SubSystem_B
Exec operation_C from SubSystem_C

三,外观模式的应用场景

系统集成:当多个组件或服务接口需要被统一管理和使用时,借助外观模式构建一个统一的入口。

API升级:当API升级时,为了兼容旧版本的API接口的使用,创建一个外观模式的对象,既可以对外提供新的API接口,又向后兼容旧的API接口。

开发第三方库或框架:针对大型的库或者框架的开发,为了简化用户的使用,隐藏底层实现,对外提供一个简单且统一的接口。

组件整合:为了让项目中兼容不同架构和使用方式的组件时,使用外观模式来规范化组件的调用方式。

四,外观模式的优缺点

外观模式的优点:

1.减少了需要客户端关注和处理的对象数,简化了接口的使用方式。

2.实现了子系统和客户端之间的解耦,使子系统的变更不会影响到客户端的调用方法。

3.降低了大型软件的编译难度,简化了大型软件在不同平台之间的移植过程。

4.对外提供接口的同时,可以针对单个子系统实现单独的优化和升级。

5.避免了客户端对内部底层逻辑的影响和破坏。

6.促进了子系统的模块化和可重用性。

外观模式的缺点:

1.对底层的过度包装会增加性能开销。

2.如果设计的不合理,会使重构变得有难度。

3.如果存在访问共享资源的情况,代码的编写不够严谨时,相同层次的子系统和子系统之间可能会互相影响。

4.子系统和子系统之间可能包含相同的功能,导致代码冗余。

五,代码实战

Demo1:模拟计算机的集成

#include <iostream>
#include <string>//subSystem
class Monitor {
public:void turnOn() {std::cout << "Monitor turned on.\n";}void turnOff() {std::cout << "Monitor turned off.\n";}
};//subSystem
class Keyboard {
public:void pressKey(int keyCode) {std::cout << "Pressed key: " << keyCode << ".\n";}
};//subSystem
class CPU {
public:void start() {std::cout << "CPU started.\n";}void stop() {std::cout << "CPU stopped.\n";}
};//Facade
class Computer {
private:Monitor monitor;Keyboard keyboard;CPU cpu;public:Computer() {}void turnOnAndStart() {monitor.turnOn();keyboard.pressKey(13);cpu.start();}void shutDown() {cpu.stop();monitor.turnOff();}
};int main() {Computer myComputer;myComputer.turnOnAndStart();myComputer.shutDown();return 0;
}

运行结果:

Monitor turned on.
Pressed key: 13.
CPU started.
CPU stopped.
Monitor turned off.

Demo1:模拟汽车的集成

#include <iostream>// Subsystem 1
class Engine {
public:void Start(){std::cout << "Engine started" << std::endl;}void Stop(){std::cout << "Engine stopped" << std::endl;}
};// Subsystem 2
class Lights {
public:void TurnOn() {std::cout << "Lights on" << std::endl;}void TurnOff(){std::cout << "Lights off" << std::endl;}
};// Facade
class Car {
private:Engine engine;Lights lights;
public:void StartCar(){engine.Start();lights.TurnOn();std::cout << "Car is ready to drive" << std::endl;}void StopCar(){lights.TurnOff();engine.Stop();std::cout << "Car has stopped" << std::endl;}
};int main()
{Car car;car.StartCar();car.StopCar();return 0;
}

运行结果:

Engine started
Lights on
Car is ready to drive
Lights off
Engine stopped
Car has stopped

六,参考阅读

https://www.geeksforgeeks.org/facade-method-c-design-patterns/

https://sourcemaking.com/design_patterns/facade

https://refactoringguru.cn/design-patterns/facade

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

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

相关文章

四十七、openlayers官网示例Image Filters——给地图添加锐化、浮雕、边缘等滤镜效果

官网demo示例&#xff1a; Image Filters 这篇讲的是如何给地图添加滤镜。 一看代码&#xff0c;&#xff0c;好家伙&#xff0c;信息量满满&#xff0c;全都看不懂。。。 咱只能一段一段扒。。。 首先添加一个底图到地图上&#xff0c;这个好理解。 const imagery new Til…

macOS vscode常用快捷键

1、shiftoption上下箭头 复制当前行 2、commandd 选定多个相同的单词 先双击选定一个单词&#xff0c;然后按下commandd 依次选中要修改的单词&#xff0c;直接修改即可 3、全局替换某个单词 comandh 4、快速定位到某一行 controlg 5、选中某个区域 shiftoption&#xff0c;然…

Adobe Photoshop cc快速抠图与精致抠图方法

一、背景 Photoshop cc绝对是最好用的抠图and修图软件&#xff0c;但是即使最简单的抠图&#xff0c;每次用时都忘记怎么做&#xff0c;然后再去B站搜&#xff0c;非常费时&#xff0c;下面记录一下抠图过程&#xff0c;方便查阅。 一、Adobe Photoshop快速抠图 选择——主体…

web系统数据库敏感数据处理

一、前言 web系统数据库中保存的公民信息不允许明文存储&#xff0c;比如手机号&#xff0c;身份证号&#xff0c;收货地址等。 二、处理方式 数据库中密文存储&#xff0c;web通过注解的方式对数据加解密处理&#xff0c;下面是处理方法 1、编写接口 public interface E…

提取人脸——OpenCV

提取人脸 导入所需的库创建窗口显示原始图片显示检测到的人脸创建全局变量定义字体对象定义一个函数select_image定义了extract_faces函数设置按钮运行GUI主循环运行显示 导入所需的库 tkinter&#xff1a;用于创建图形用户界面。 filedialog&#xff1a;用于打开文件对话框。 …

【JS】上传文件显示文件的为空,显示的文件参数内容只有uid

上传的文件参数file里面只包含uid&#xff0c;没有其他信息 例子解决办法 例子 例如使用elment ui的el-upload组件上传文件&#xff0c;会导致上传的文件参数file里面只包含uid&#xff0c;没有其他信息&#xff0c;如图&#xff1a; 正确应为如下图&#xff1a; 解决办法 …

MySQL 基本语法讲解及示例(上)

第一节&#xff1a;MySQL的基本操作 1. 创建数据库 在 MySQL 中&#xff0c;创建数据库的步骤如下&#xff1a; 命令行操作 打开 MySQL 命令行客户端或连接到 MySQL 服务器。 输入以下命令创建一个数据库&#xff1a; CREATE DATABASE database_name;例如&#xff0c;创建一…

了解Nest.js

一直做前端开发&#xff0c;都会有成为全栈工程师的想法&#xff0c;而 Nest 就是一个很好的途径&#xff0c;它是 Node 最流行的企业级开发框架&#xff0c;提供了 IOC、AOP、微服务等架构特性。接下来就让我们一起来学习Nest.js Nest.js官网地址 一&#xff0c;了解Nest Cli …

第十二章:会话控制

会话控制 文章目录 会话控制一、介绍二、cookie2.1 cookie 是什么2.2 cookie 的特点2.3 cookie 的运行流程2.4 浏览器操作 cookie2.5 cookie 的代码操作&#xff08;1&#xff09;设置 cookie&#xff08;2&#xff09;读取 cookie&#xff08;3&#xff09;删除 cookie 三、se…

56.SAP MII开发的一个系统响应错误 Error code: ICMETIMEOUT

问题 一个SAP MII开发的项目&#xff0c;最近新增了一个功能&#xff0c;查询数据源量比较大&#xff0c;逻辑有点复杂&#xff0c;大约7-8分钟。发布到生产系统后&#xff0c;发生响应错误&#xff0c;返回 Error code: ICMETIMEOUT <!-- Error code: ICMETIMEOUT -->\r…

Petalinux由于网络原因产生的编译错误(2)--Fetcher failure:Unable to find file

1 Fetcher failure:Unable to find file 错误 如果编译工程遇到如下图所示的“Fetcher failure for URL”或相似错误 出现这种错误的原因是 Petalinux 在配置和编译的时候&#xff0c;需要联网下载一些文件&#xff0c;由于网 络原因这些文件不能正常下载&#xff0c;导致编译…

Vue 路由:一级路由,嵌套路由

1、安装路由插件,因为用的是vue2 所以路由版本要和vue2对应上&#xff0c;所有有3 yarn add vue-router3 2、在main.js里引入 import VueRouter from vue-router Vue.use(VueRouter) 3、新建文件夹 router,创建index.js 4、引入路由插件&#xff0c;并且暴露出来这个路由 5、在…

「TCP 重要机制」滑动窗口 粘包问题 异常情况处理

&#x1f387;个人主页&#xff1a;Ice_Sugar_7 &#x1f387;所属专栏&#xff1a;计网 &#x1f387;欢迎点赞收藏加关注哦&#xff01; 滑动窗口&粘包问题&异常情况处理 &#x1f349;滑动窗口&#x1f34c;流量控制&#x1f34c;拥塞控制&#x1f34c;延时应答&…

Docker overlay磁盘使用100%处理方法overlay 100%

一、问题描述 服务器上运行了几个docker容器,运行个一周就会出现overlay 100%的情况&#xff0c;经查找&#xff0c;是容器里生成了很多core.xxx的文件导致的。 二、解决方法 首先通过以下命令查看&#xff1a; df -h 可以看的overlay已经100%了&#xff0c;进入到/var/lib/d…

C++之std::type_identity

目录 1.简介 2.C20的std::type_identity 3.使用 type_identity 3.1.阻止参数推导 3.1.1.模板参数推导过程中的隐式类型转换 3.1.2.强制显式实例化 3.2.阻止推断指引 3.3.类型保持 3.4.满足一些稀奇古怪的语法 4.示例 5.总结 1.简介 std::type_identity 是 C17 引入的…

element-ui将组件默认语言改为中文

在main.js中加入以下代码即可 // 引入 Element Plus 及其样式 import ElementPlus from element-plus import element-plus/dist/index.css// 引入中文语言包 import zhCn from element-plus/es/locale/lang/zh-cn// 使用 Element Plus 并设置语言为中文 app.use(ElementPlus,…

RNN的变种们:GRULSTM双向RNN

上篇笔记记录到RNN的一个缺点&#xff1a;训练时会出现梯度消失&#xff0c;解决的办法是找到一个更优的计算单元。这里也有GRU和LSTM。 GRU&#xff08;Gated Recurrent Unit&#xff09;门控训练网络 什么是门控机制&#xff1f;就是对当前的输入进行一个筛选。门打开&…

从零开始写 Docker(十八)---容器网络实现(下):为容器插上”网线“

本文为从零开始写 Docker 系列第十八篇&#xff0c;利用 linux 下的 Veth、Bridge、iptables 等等相关技术&#xff0c;构建容器网络模型&#xff0c;为容器插上”网线“。 完整代码见&#xff1a;https://github.com/lixd/mydocker 欢迎 Star 推荐阅读以下文章对 docker 基本实…

私域引流宝PHP源码 以及搭建教程

私域引流宝PHP源码 以及搭建教程

LeetCode 算法:合并两个有序链表 c++

原题链接&#x1f517;&#xff1a;合并两个有序链表 难度&#xff1a;简单⭐️ 题目 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1&#xff1a; 输入&#xff1a;l1 [1,2,4], l2 [1,3,4] 输出&#xff1a;…