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.…...
避开这些坑!Sigma-Delta调制器设计中最容易忽略的5个稳定性问题(附MASH级联实测数据)
避开这些坑!Sigma-Delta调制器设计中最容易忽略的5个稳定性问题(附MASH级联实测数据) 在高速高精度ADC设计中,Sigma-Delta调制器因其优异的噪声整形特性成为首选方案。但当工程师们沉浸在理论计算的理想世界时,实验室示…...
农机经销商必看:如何用2000-2020年县级数据精准定位区域市场?
农机经销商区域市场精准定位实战指南:基于2000-2020年县级数据分析 站在山东潍坊的田间地头,老张望着远处几台正在作业的拖拉机陷入了沉思。作为一家中型农机经销商的区域经理,他每年最头疼的就是如何准确预测各县区的农机需求——备货多了占…...
模拟IC工程师必备:用Cadence Virtuoso仿真电流镜的7个关键步骤
模拟IC工程师必备:用Cadence Virtuoso仿真电流镜的7个关键步骤 在模拟集成电路设计中,电流镜堪称"细胞级"的基础模块,其性能直接影响整个系统的精度与稳定性。对于刚接触Cadence Virtuoso的工程师而言,如何高效完成从电…...
Vivado中OSD核报错全攻略:从IP_flow 19-167到BD 41-1030的解决方案
Vivado中OSD核报错全攻略:从IP_flow 19-167到BD 41-1030的解决方案 在FPGA开发过程中,Xilinx Vivado工具链的OSD(On-Screen Display)核是一个常用的视频处理IP,但开发者常会遇到各种报错问题。本文将深入解析从IP_flo…...
ROS2 Humble下,如何用一份Xacro文件同时搞定MoveIt2配置与Gazebo仿真(附完整Launch文件)
ROS2 Humble统一建模实战:Xacro文件在MoveIt2与Gazebo中的协同设计 当机械臂的URDF文件需要同时满足MoveIt2的运动规划需求和Gazebo的物理仿真要求时,开发者往往陷入两难境地。传统方案需要维护两份模型文件——一份精简版用于MoveIt,另一份增…...
遥感影像配准总对不齐?OpenCV+RST+PROJ4三重坐标系对齐实战(附WGS84→UTM→影像本地坐标的转换矩阵速查表)
第一章:Shell脚本的基本语法和命令Shell脚本是Linux/Unix系统自动化任务的核心工具,以可执行文本文件形式存在,由Bash等shell解释器逐行解析运行。其语法简洁但严谨,对空格、分号、引号和换行符敏感,需严格遵循语法规则…...
别再为IP冲突头疼!YOLOv5+海康威视摄像头组网与实时检测的完整避坑指南
工业视觉组网实战:YOLOv5与海康威视摄像头的智能协同方案 在智能制造与安防监控领域,将AI算法与专业摄像设备结合已成为技术标配。但当工程师真正着手部署时,往往会陷入网络配置的泥潭——IP冲突导致设备失联、RTSP流媒体断断续续、多网卡环…...
ESP32嵌入式系统设计与实现指南
1. 项目概述1.1 系统架构本项目基于ESP32主控芯片设计,采用模块化架构实现多功能嵌入式系统。系统包含以下核心模块:主控单元:ESP32-WROOM-32D模组电源管理:TPS63020升降压转换器传感器接口:I2C/SPI多协议兼容设计人机…...
springboot基于协同过滤推荐算法的图书借阅推荐系统
目录需求分析与系统设计数据准备与处理协同过滤算法实现推荐系统集成系统测试与优化部署与监控项目技术支持源码获取详细视频演示 :文章底部获取博主联系方式!同行可合作需求分析与系统设计 明确系统的核心功能需求,包括用户管理、图书管理、…...
电赛小车避坑指南:从2011到2024,那些年我们踩过的传感器和通信模块的‘坑’
电赛小车避坑指南:从2011到2024,那些年我们踩过的传感器和通信模块的"坑" 参加全国大学生电子设计竞赛的同学们都知道,小车控制类赛题一直是热门选项。从2011年的双车自主超车到2024年的自动行驶小车,这些题目看似简单&…...
