12.外观模式(Facade Pattern)
定义
外观模式(Facade Pattern) 是一种结构型设计模式,它通过为复杂的子系统提供一个统一的接口,使得子系统的使用更加简化。外观模式通常隐藏了复杂的内部子系统,使得客户端可以通过一个简单的接口与这些子系统进行交互。
核心思想:
简化接口:通过提供一个简单的接口来封装复杂的子系统。
解耦:客户端不需要了解子系统的内部实现,只需与外观类交互,降低了系统的复杂性。
适用场景
外观模式适用于以下场景:
- 简化复杂系统:当系统中有多个复杂的子系统时,使用外观模式提供一个简单的接口,以减少客户端与子系统的交互复杂度。
- 解耦客户端与子系统:客户端无需知道子系统内部的工作原理,只需与外观类交互即可。
- 多层次接口:当系统提供了多个接口,并且这些接口之间有复杂的交互时,使用外观模式可以通过统一接口简化调用。
常见应用场景:
- 音响系统控制:将复杂的音响系统(如播放、调整音量、切换输入源等)通过外观模式提供一个简单的接口进行控制。
- 家庭自动化系统:例如,控制家庭的智能设备(照明、安防、温控等)可以通过一个统一的控制接口进行操作。
类设计
外观模式的设计通常包括以下角色:
1.Facade(外观类):为客户端提供简化的接口,它与子系统进行交互。
2.Subsystem(子系统):复杂的子系统,提供实际的功能实现。
3.Client(客户端):通过外观类与子系统交互。
代码实现解析
假设我们有一个家庭影院系统,系统包括音响、投影仪、DVD 播放器和灯光等多个组件。我们希望通过外观模式来简化控制这些组件的操作。
子系统类设计:
#include <iostream>
#include <string>
using namespace std;class Amplifier {
public:void on() {cout << "Amplifier on" << endl;}void off() {cout << "Amplifier off" << endl;}void setVolume(int level) {cout << "Setting volume to " << level << endl;}
};class Projector {
public:void on() {cout << "Projector on" << endl;}void off() {cout << "Projector off" << endl;}void wideScreenMode() {cout << "Projector in widescreen mode" << endl;}
};class DVDPlayer {
public:void on() {cout << "DVD Player on" << endl;}void off() {cout << "DVD Player off" << endl;}void play(string movie) {cout << "Playing movie: " << movie << endl;}void stop() {cout << "Stopping movie" << endl;}
};class Lights {
public:void dim(int level) {cout << "Dimming lights to " << level << "%" << endl;}void on() {cout << "Lights on" << endl;}
};
外观类设计:
class HomeTheaterFacade {
private:Amplifier* amplifier;Projector* projector;DVDPlayer* dvdPlayer;Lights* lights;public:HomeTheaterFacade(Amplifier* amp, Projector* proj, DVDPlayer* dvd, Lights* light) :amplifier(amp), projector(proj), dvdPlayer(dvd), lights(light) {}void watchMovie(string movie) {cout << "Get ready to watch a movie..." << endl;lights->dim(10);projector->on();projector->wideScreenMode();amplifier->on();amplifier->setVolume(5);dvdPlayer->on();dvdPlayer->play(movie);}void endMovie() {cout << "Shutting down the movie theater..." << endl;lights->on();projector->off();amplifier->off();dvdPlayer->stop();dvdPlayer->off();}
};
客户端调用:
int main() {Amplifier* amplifier = new Amplifier();Projector* projector = new Projector();DVDPlayer* dvdPlayer = new DVDPlayer();Lights* lights = new Lights();// 创建外观对象,简化子系统接口HomeTheaterFacade* homeTheater = new HomeTheaterFacade(amplifier, projector, dvdPlayer, lights);// 客户端通过外观类调用子系统的功能homeTheater->watchMovie("Inception");homeTheater->endMovie();delete amplifier;delete projector;delete dvdPlayer;delete lights;delete homeTheater;return 0;
}
输出如下:
Get ready to watch a movie...
Dimming lights to 10%
Projector on
Projector in widescreen mode
Amplifier on
Setting volume to 5
DVD Player on
Playing movie: Inception
Shutting down the movie theater...
Lights on
Projector off
Amplifier off
Stopping movie
DVD Player off
可以看到,客户端通过 HomeTheaterFacade 只调用了 watchMovie 和 endMovie 两个方法,就完成了多个子系统的操作。HomeTheaterFacade 为客户端提供了一个简单的接口,屏蔽了子系统的复杂性。
类设计分析
1.子系统类:这些类(Amplifier、Projector、DVDPlayer、Lights)是独立的子系统,负责实现实际的功能。
- 每个子系统类都有复杂的内部实现,客户端不需要直接与这些类交互。
2.外观类(HomeTheaterFacade):
- HomeTheaterFacade 类封装了所有子系统的操作,它通过提供简化的 watchMovie 和 endMovie 方法来控制整个家庭影院系统。
- 外观类与所有子系统类交互,客户端只需要调用外观类的方法,而无需关心如何具体操作每个子系统。
3.客户端:客户端代码通过 HomeTheaterFacade 与所有子系统进行交互,而无需了解子系统的具体实现。
总结
Facade 模式的优点:
- 简化接口:将复杂子系统的接口进行封装,提供统一的简单接口。
- 解耦:客户端不再与子系统的多个组件交互,只与外观类交互,减少了系统之间的耦合。
- 提高可维护性:外观模式通过将子系统的复杂性隐藏在外观类中,使得系统的维护更加容易
Facade 模式的缺点:
- 增加了外观类的复杂性:随着子系统的增多,外观类可能变得较为庞大,维护时需要确保其接口不会被滥用。
- 可能导致过度设计:如果系统本身比较简单,使用外观模式可能是过度设计,增加了不必要的复杂度。
Facade 模式的适用场景
- 简化复杂的子系统接口:当系统有多个复杂的子系统时,可以使用外观模式来提供统一的简单接口。
- 降低子系统间的耦合:当不同子系统之间的依赖性较强时,外观模式能有效隔离这些子系统,减少系统间的相互依赖。
- 提供一个高层接口:当多个子系统的调用顺序复杂时,外观模式能提供一个简化的接口。
总结:
外观模式通过为复杂的系统提供一个简单的接口,简化了系统的使用和管理。客户端无需了解系统内部的复杂实现,只需要与外观类交互,外观类负责协调多个子系统的操作。外观模式通常用于简化客户端与子系统之间的交互,并提高系统的可维护性。
相关文章:
12.外观模式(Facade Pattern)
定义 外观模式(Facade Pattern) 是一种结构型设计模式,它通过为复杂的子系统提供一个统一的接口,使得子系统的使用更加简化。外观模式通常隐藏了复杂的内部子系统,使得客户端可以通过一个简单的接口与这些子系统进行交…...
ES6 入门教程:箭头函数、解构赋值及其他新特性详解
ES6 入门教程:箭头函数、解构赋值及其他新特性详解 ES6 入门教程:箭头函数、解构赋值及其他新特性详解引言什么是 ES6?箭头函数(Arrow Functions)1. 基本语法2. 常见特点(1)没有自己的 this 上下…...
win编译openssl
一、perl执行脚本 1、安装perl脚本 perl安装 2、配置perl脚本 perl Configure VC-WIN32 no-asm no-shared --prefixE:\openssl-x.x.x\install二、编译openssl 1、使用vs工具编译nmake 如果使用命令行nmake编译会提示“无法打开包括文件: “limits.h”“ 等错误信息 所以…...
51单片机看门狗系统
在 STC89C52 单片机中,看门狗控制寄存器的固定地址为 0xE1。此地址由芯片厂商在硬件设计时确定,但是它在头文件中并未给出,因此在使用看门狗系统时需要声明下这个特殊功能寄存器 sfr WDT_CONTR 0xE1; 本案将用一个小灯的工作状况来展示看门…...
探索 paraphrase-MiniLM-L6-v2 模型在自然语言处理中的应用
在自然语言处理(NLP)领域,将文本数据转换为机器学习模型可以处理的格式是至关重要的。近年来,sentence-transformers 库因其在文本嵌入方面的卓越表现而受到广泛关注。本文将深入探讨 paraphrase-MiniLM-L6-v2 模型,这…...
2025最新软件测试面试大全(附答案+文档)
🍅 点击文末小卡片 ,免费获取软件测试全套资料,资料在手,涨薪更快 1、问:你在测试中发现了一个bug,但是开发经理认为这不是一个bug,你应该怎样解决? 首先,将问题提交到缺陷管理库里…...
Java语法进阶
目录: Object类、常用APICollection、泛型List、Set、数据结构、CollectionsMap与斗地主案例异常、线程线程、同步等待与唤醒案例、线程池、Lambda表达式File类、递归字节流、字符流缓冲流、转换流、序列化流、Files网络编程 十二、函数式接口Stream流、方法引用 一…...
UNI-MOL: A UNIVERSAL 3D MOLECULAR REPRESENTATION LEARNING FRAMEWORK
UNI-MOL: A UNIVERSAL 3D MOLECULAR REPRESENTATION LEARNING FRAMEWORK Neurips23 推荐指数:#paper/⭐⭐⭐#(工作量不小) 动机 在大多数分子表征学习方法中,分子被视为 1D 顺序标记或2D 拓扑图,这限制了它们为下游任务整合…...
笔记day7
文章目录 1 分页功能实现2 分页器的展示需要哪些数据(条件)?3 自定义分页器4 分页器存在问题5 分页器动态展示6 开发某一个商品的详情页面 1 分页功能实现 为什么很多项目采用分页功能,比如电商平台同时展示的数据有很多…...
106,【6】 buuctf web [SUCTF 2019]CheckIn
进入靶场 文件上传 老规矩,桌面有啥传啥 过滤了<? 寻找不含<?的一句话木马 文件名 123(2).php.jpg 文件内容 GIF89a? <script language"php">eval($_GET[123]);</script> 123即密码,可凭借个人喜好更换 再上传一个文…...
基于Ubuntu2404搭建Zabbix7.2
Zabbix 搭建zabbix zabbix7.2已推出:官网 增加的新功能如下: 1.使用新的热门商品小部件全面概览指标 数据概览小部件已转换为热门项目小部件使用项目模式可以实现细粒度的项目选择利用条形图、指标和迷你图来可视化您的数据定义价值阈值以动态地可视化…...
OPENGLPG第九版学习 - 着色器基础
文章目录 2.1 着色器与OpenGL2.2 0penGL的可编程管线2.3 OpenGL着色语言GLSL概述2.3.1 使用GLSL构建着色器变量的声明变量的作用域变量的初始化构造函数 、 类型转换聚合类型访问向量和矩阵中的元素结构体数组多维数组 2.3.2 存储限制符const 存储限制符in 存储限制符out 存储限…...
Android 使用ExpandableListView时,需要注意哪些细节
1. 布局属性设置 尺寸属性 宽度和高度:要合理设置 android:layout_width 和 android:layout_height 属性。如果设置为 match_parent,它会填满父容器;设置为 wrap_content,则会根据内容自动调整大小。例如,若想让 Exp…...
redis简介及应用
文章目录 1.redis简介2.安装配置2.1 单机部署2.2 配置 3 主从部署4 哨兵部署5.集群部署6.客户端工具 1.redis简介 某些网站出现的问题,如12306、淘宝等… 2.安装配置 2.1 单机部署 安装gcc、关闭防火墙、关闭selinux等 #安装gcc yum -y install gcc #关闭防火墙…...
Electron使用WebAssembly实现CRC-8 MAXIM校验
Electron使用WebAssembly实现CRC-8 MAXIM校验 将C/C语言代码,经由WebAssembly编译为库函数,可以在JS语言环境进行调用。这里介绍在Electron工具环境使用WebAssembly调用CRC-8 MAXIM格式校验的方式。 CRC-8 MAXIM校验函数WebAssembly源文件 C语言实现C…...
人工智能赋能企业系统架构设计:以ERP与CRM系统为例
一、引言 1.1 研究背景与意义 在数字化时代,信息技术飞速发展,人工智能(Artificial Intelligence, AI)作为一项具有变革性的技术,正深刻地影响着各个领域。近年来,AI 在技术上取得了显著突破,…...
NacosRce到docker逃逸实战
NacosRce到docker逃逸实战 1、Nacos Derby Rce打入内存马 这个漏洞的原理大家应该都知道, 2.3.2 < Nacos < 2.4.0版本默认derby接口未授权访问,攻击者可利用未授权访问执行SQL语句加载构造恶意的JAR包导致出现远程代码执行漏洞。 在日常的漏洞挖…...
Linux:文件系统(软硬链接)
目录 inode ext2文件系统 Block Group 超级块(Super Block) GDT(Group Descriptor Table) 块位图(Block Bitmap) inode位图(Inode Bitmap) i节点表(inode Tabl…...
在Spring Cloud中将Redis共用到Common模块
前言 在分布式系统中,共用组件的设计可以极大地提升代码复用性和维护性。Spring Cloud中将Redis共用到一个公共模块(common模块)是一个常见的设计实践,这样可以让多个微服务共享相同的Redis配置和操作逻辑。本文将详细介绍如何在…...
如何解决 Vue 应用中的内存泄漏
如何解决 Vue 应用中的内存泄漏 如何解决 Vue 应用中的内存泄漏常见的内存泄漏原因1. 组件生命周期管理不善2. 闭包引起的引用3. 数据订阅与发布系统4. 第三方库的内存泄漏5. 路由缓存和组件实例堆积排查内存泄漏的工具1. **Chrome DevTools**2. **Firefox Developer Tools**3.…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...
CMake基础:构建流程详解
目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...
质量体系的重要
质量体系是为确保产品、服务或过程质量满足规定要求,由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面: 🏛️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限,形成层级清晰的管理网络…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...
技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...
在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案
这个问题我看其他博主也写了,要么要会员、要么写的乱七八糟。这里我整理一下,把问题说清楚并且给出代码,拿去用就行,照着葫芦画瓢。 问题 在继承QWebEngineView后,重写mousePressEvent或event函数无法捕获鼠标按下事…...
【Linux系统】Linux环境变量:系统配置的隐形指挥官
。# Linux系列 文章目录 前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变量的生命周期 四、环境变量的组织方式五、C语言对环境变量的操作5.1 设置环境变量:setenv5.2 删除环境变量:unsetenv5.3 遍历所有环境…...
0x-3-Oracle 23 ai-sqlcl 25.1 集成安装-配置和优化
是不是受够了安装了oracle database之后sqlplus的简陋,无法删除无法上下翻页的苦恼。 可以安装readline和rlwrap插件的话,配置.bahs_profile后也能解决上下翻页这些,但是很多生产环境无法安装rpm包。 oracle提供了sqlcl免费许可,…...
《信号与系统》第 6 章 信号与系统的时域和频域特性
目录 6.0 引言 6.1 傅里叶变换的模和相位表示 6.2 线性时不变系统频率响应的模和相位表示 6.2.1 线性与非线性相位 6.2.2 群时延 6.2.3 对数模和相位图 6.3 理想频率选择性滤波器的时域特性 6.4 非理想滤波器的时域和频域特性讨论 6.5 一阶与二阶连续时间系统 6.5.1 …...
node.js的初步学习
那什么是node.js呢? 和JavaScript又是什么关系呢? node.js 提供了 JavaScript的运行环境。当JavaScript作为后端开发语言来说, 需要在node.js的环境上进行当JavaScript作为前端开发语言来说,需要在浏览器的环境上进行 Node.js 可…...
