C# 设计模式(结构型模式):外观模式
C# 设计模式(结构型模式):外观模式 (Facade Pattern)
在复杂系统中,往往会涉及到多个子系统、模块和类。这些子系统的接口和功能可能会让使用者感到困惑和复杂。在这种情况下,我们可以使用外观模式(Facade Pattern)来简化系统的操作。外观模式通过提供一个统一的接口来隐藏复杂的子系统,使得客户端可以更容易地与系统进行交互。
1. 外观模式的定义
外观模式是一种结构型设计模式,它为复杂子系统提供一个简化的接口。通过引入外观对象,客户端只需要与外观对象交互,避免直接操作复杂的子系统。外观模式能够减少客户端和多个子系统之间的耦合关系,并且提高系统的易用性。
2. 外观模式的结构
外观模式的结构主要包括以下几部分:
- Facade(外观类):提供一个统一的接口,封装对多个子系统的调用。
- Subsystem Classes(子系统类):多个子系统类,封装了具体的业务逻辑。外观类通过调用这些子系统的接口来实现所需的功能。
- Client(客户端):客户端通过外观类来调用子系统,而无需直接接触子系统的复杂接口。
3. 外观模式的应用场景
外观模式适用于以下几种场景:
- 简化接口:当一个系统或子系统变得过于复杂时,外观模式可以为其提供一个简化的接口,降低使用门槛。
- 子系统之间解耦:外观模式可以帮助将复杂子系统的操作封装起来,减少客户端与多个子系统之间的耦合度。
- 减少客户端对系统内部实现的依赖:客户端只需要知道如何与外观类交互,而不需要了解系统内部的实现细节。
4. C# 实现外观模式
假设我们有一个家庭影院系统,包括多个设备如音响、投影仪、灯光和蓝光播放器。每个设备都有自己独立的操作接口,客户端操作起来非常繁琐。我们可以通过外观模式来简化操作,客户端只需要与外观类交互,而不必关心各个设备的具体操作。
示例:家庭影院系统的外观模式
using System;// 子系统类:音响
public class SoundSystem
{public void On() => Console.WriteLine("Turning on the sound system...");public void Off() => Console.WriteLine("Turning off the sound system...");public void SetVolume(int volume) => Console.WriteLine($"Setting volume to {volume}.");
}// 子系统类:投影仪
public class Projector
{public void On() => Console.WriteLine("Turning on the projector...");public void Off() => Console.WriteLine("Turning off the projector...");public void SetMode() => Console.WriteLine("Setting projector mode to 1080p.");
}// 子系统类:灯光
public class Lights
{public void On() => Console.WriteLine("Turning on the lights...");public void Off() => Console.WriteLine("Turning off the lights...");public void Dim(int level) => Console.WriteLine($"Dimming lights to {level}%.");
}// 子系统类:蓝光播放器
public class BluRayPlayer
{public void On() => Console.WriteLine("Turning on the Blu-ray player...");public void Off() => Console.WriteLine("Turning off the Blu-ray player...");public void PlayMovie(string movie) => Console.WriteLine($"Playing movie: {movie}");
}// 外观类:家庭影院外观
public class HomeTheaterFacade
{private SoundSystem soundSystem;private Projector projector;private Lights lights;private BluRayPlayer bluRayPlayer;public HomeTheaterFacade(SoundSystem soundSystem, Projector projector, Lights lights, BluRayPlayer bluRayPlayer){this.soundSystem = soundSystem;this.projector = projector;this.lights = lights;this.bluRayPlayer = bluRayPlayer;}// 启动家庭影院public void WatchMovie(string movie){Console.WriteLine("Get ready to watch a movie...");lights.Dim(10); // 调暗灯光projector.On(); // 打开投影仪projector.SetMode(); // 设置投影仪模式soundSystem.On(); // 打开音响系统soundSystem.SetVolume(20); // 设置音量bluRayPlayer.On(); // 打开蓝光播放器bluRayPlayer.PlayMovie(movie); // 播放电影}// 关闭家庭影院public void EndMovie(){Console.WriteLine("Shutting down the home theater...");lights.On(); // 打开灯光projector.Off(); // 关闭投影仪soundSystem.Off(); // 关闭音响bluRayPlayer.Off(); // 关闭蓝光播放器}
}// 客户端代码
class Program
{static void Main(string[] args){// 创建子系统对象SoundSystem soundSystem = new SoundSystem();Projector projector = new Projector();Lights lights = new Lights();BluRayPlayer bluRayPlayer = new BluRayPlayer();// 创建外观对象HomeTheaterFacade homeTheater = new HomeTheaterFacade(soundSystem, projector, lights, bluRayPlayer);// 客户端通过外观类与系统交互homeTheater.WatchMovie("Inception"); // 启动家庭影院,观看电影Console.WriteLine();homeTheater.EndMovie(); // 关闭家庭影院}
}
代码解析:
- 子系统类(如
SoundSystem、Projector等)分别负责家庭影院的各个设备操作。 - 外观类
HomeTheaterFacade提供了一个简化的接口WatchMovie和EndMovie,客户端可以通过外观类来简化多个设备的操作,而无需直接与子系统类交互。 - 客户端代码:客户端通过外观类
HomeTheaterFacade来启动和关闭家庭影院系统,无需关心各个设备的详细操作。
运行结果:
Get ready to watch a movie...
Dimming lights to 10%.
Turning on the projector...
Setting projector mode to 1080p.
Turning on the sound system...
Setting volume to 20.
Turning on the Blu-ray player...
Playing movie: InceptionShutting down the home theater...
Turning on the lights...
Turning off the projector...
Turning off the sound system...
Turning off the Blu-ray player...
5. 外观模式的优缺点
优点:
- 简化客户端操作:外观模式通过提供一个统一的接口,简化了客户端与多个子系统的交互,避免了复杂的操作。
- 解耦:外观模式将客户端与多个子系统解耦,减少了系统间的依赖关系。
- 提高可维护性:通过引入外观类,修改子系统时不需要修改客户端代码,从而提高了系统的可维护性。
缺点:
- 可能导致过于庞大的外观类:如果系统过于复杂,外观类可能会变得非常庞大,导致维护困难。
- 限制了子系统的灵活性:外观模式将子系统的功能封装在外观类中,可能会限制客户端直接使用子系统的某些高级功能。
6. 总结
外观模式是一种结构型设计模式,通过提供一个简化的接口,隐藏了系统中复杂的子系统细节。它帮助减少了客户端与多个子系统之间的耦合,提高了系统的可维护性和易用性。在复杂系统中,外观模式能够有效地简化用户操作,尤其适用于需要协调多个子系统工作的场景。
希望这篇文章能够帮助你理解外观模式的概念与应用!如果你有任何问题或需要进一步讨论,欢迎随时联系我!
相关文章:
C# 设计模式(结构型模式):外观模式
C# 设计模式(结构型模式):外观模式 (Facade Pattern) 在复杂系统中,往往会涉及到多个子系统、模块和类。这些子系统的接口和功能可能会让使用者感到困惑和复杂。在这种情况下,我们可以使用外观模式(Facade…...
PowerShell 常见问题解答
PowerShell 是微软开发的一种功能强大的命令行界面和脚本语言,广泛应用于系统管理和自动化任务。以下是一些使用 PowerShell 时常见的问题及其解决方法。 什么是 PowerShell? PowerShell 是基于 .NET 的命令行界面(CLI)和脚本语言…...
计算机网络 (15)宽带接入技术
前言 计算机网络宽带接入技术是指通过高速、大容量的通信信道或网络,实现用户与互联网或其他通信网络之间的高速连接。 一、宽带接入技术的定义与特点 定义:宽带接入技术是指能够传输大量数据的通信信道或网络,其传输速度通常较高,…...
前端Python应用指南(六)构建RESTful API:使用Flask和Django实现用户认证与授权
《写给前端的python应用指南》系列: (一)快速构建 Web 服务器 - Flask vs Node.js 对比(二)深入Flask:理解Flask的应用结构与模块化设计(三)Django vs Flask:哪种框架适…...
【Unity3D】基于UGUI——简易版 UI框架
https://github.com/AMikeW/BStandShaderResources/blob/master/milk_UIFramework.unitypackage UI框架支持如下功能: 1、层级控制 2、支持面板多次打开时,隐藏前一个打开的面板,当关闭面板时,能够恢复前一个打开面板状态 3、支…...
算法排序算法
文章目录 快速排序[leetcode 215数组中的第K个最大元素](https://leetcode.cn/problems/kth-largest-element-in-an-array/)分析题解快速排序 桶排序[leetcode 347 前K个高频元素](https://leetcode.cn/problems/top-k-frequent-elements/)分析题解 快速排序 leetcode 215数组…...
第3章 总线
总线的定义 为多个部件 分时共享 公共信息传送线路。 系统之间、模块之间、芯片内部用来传递信息信号线集合。 共享 总线上可连接多个部件 各部件间相互交换信息 都可通过总线来。 分时 同一时刻 总线上只能传 一个部件信息。 采用标准总线的优点 简化系统软硬件设计 从硬件角度…...
手机实时提取SIM卡打电话的信令声音-双卡手机来电如何获取哪一个卡的来电
手机实时提取SIM卡打电话的信令声音 --双卡手机来电如何获取哪一个卡的来电 一、前言 前面的篇章《手机实时提取SIM卡打电话的信令声音-智能拨号器的双SIM卡切换方案》中,我们论述了局域网SIP坐席通过手机外呼出去时,手机中主副卡的呼叫调度策略。 但…...
共阳极LED的控制与短路问题解析
共阳极LED的控制与短路问题解析 在电子电路中,LED(发光二极管)是最常见的元件之一。LED的连接方式分为共阳极和共阴极,不同的连接方式决定了LED的控制逻辑。本文将重点讲解共阳极LED的工作原理,并解答“为什么给1不会…...
华为消费级QLC SSD来了
近日,有关消息显示,华为的消费级SSD产品线,eKitStor Xtreme 200E系列,在韩国一家在线零售商处首次公开销售,引起了业界的广泛关注。 尽管华为已经涉足服务器级别的SSD制造多年,但直到今年6月才正式推出面向…...
liunx下载gitlab
1.地址: https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/ 安装 postfix 并启动 yum install postfix systemctl start postfix systemctl enable postfix ssh服务启动 systemctl enable sshd systemctl start sshd开放 ssh 以及 http 服务,…...
深度学习模型预测值集中在某一个值
深度学习模型,训练过程中,经常遇到预测的结果集中在某个值,而且在学习的过程中会变,样例如下。 主要有如下解决方案 1、更换relu ->tanh 或者其他激活函数 2、更改随机种子,估计是没有初始化好,或者调…...
Sqoop的使用
每个人的生活都是一个世界,即使最平凡的人也要为他那个世界的存在而战斗。 ——《平凡的世界》 目录 一、sqoop简介 1.1 导入流程 1.2 导出流程 二、使用sqoop 2.1 sqoop的常用参数 2.2 连接参数列表 2.3 操作hive表参数 2.4 其它参数 三、sqoop应用 - 导入…...
OpenGL ES 04 图片数据是怎么写入到对应纹理单元的
从指定路径加载图像并转换为 CGImage。获取图像的宽度和高度。创建一个 RGB 颜色空间。为图像数据分配内存。创建一个位图上下文并将图像绘制到上下文中。创建一个新的纹理对象并绑定到指定的纹理单元。指定二维纹理图像。释放分配的内存。设置纹理参数,包括放大和缩…...
C# 设计模式的六大原则(SOLID)
C# 设计模式的六大原则(SOLID) 引言 在面向对象编程中,设计模式提供了高效、可复用和可维护的代码结构。SOLID原则是软件设计中的一组重要原则,用于确保代码具有良好的可维护性、可扩展性和灵活性。SOLID是五个设计原则的首字母…...
数据库自增 id 过大导致前端时数据丢失
可以看到,前端响应参数是没有丢失精度的 但是在接受 axios 请求参数时出现了精度丢失 解决方案一:改变 axios 字符编码 axios.defaults.headers[Content-Type] application/json;charsetUTF-8; 未解决 解决方案二:手动使用 json.parse() …...
第二十六天 自然语言处理(NLP)词嵌入(Word2Vec、GloVe)
自然语言处理(NLP)中的词嵌入(Word2Vec、GloVe)技术,是NLP领域的重要组成部分,它们为词汇提供了高维空间到低维向量的映射,使得语义相似的词汇在向量空间中的距离更近。以下是对这些技术的详细解…...
MongoDB 固定集合
MongoDB 固定集合 MongoDB中的固定集合(Capped Collections)是一种具有固定大小的集合,当集合中的数据达到其最大大小时,它会自动覆盖最早的文档。这种类型的集合在MongoDB中用于实现高效的、固定大小的循环缓冲区。本文将详细介…...
数据结构9.3 - 文件基础(C++)
目录 1 打开文件字符读写关闭文件 上图源自:https://blog.csdn.net/LG1259156776/article/details/47035583 1 打开文件 法 1法 2ofstream file(path);ofstream file;file.open(path); #include<bits/stdc.h> using namespace std;int main() {char path[]…...
Leetcode 1254 Number of Closed Islands + Leetcode 1020 Number of Enclaves
Leetcode 1254 题意 给定一个m*n的矩阵含有0和1,1代表水,0代表陆地,岛屿是陆地的集合,如果一个岛屿和四个方向的边界相连,则不算封闭岛屿。求有多少个封闭的岛屿。 题目链接 https://leetcode.com/problems/number…...
阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...
2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面
代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...
多模态大语言模型arxiv论文略读(108)
CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题:CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者:Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...
3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...
虚拟电厂发展三大趋势:市场化、技术主导、车网互联
市场化:从政策驱动到多元盈利 政策全面赋能 2025年4月,国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》,首次明确虚拟电厂为“独立市场主体”,提出硬性目标:2027年全国调节能力≥2000万千瓦࿰…...
[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.
ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #:…...
NPOI操作EXCEL文件 ——CAD C# 二次开发
缺点:dll.版本容易加载错误。CAD加载插件时,没有加载所有类库。插件运行过程中用到某个类库,会从CAD的安装目录找,找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库,就用插件程序加载进…...
基于Java+VUE+MariaDB实现(Web)仿小米商城
仿小米商城 环境安装 nodejs maven JDK11 运行 mvn clean install -DskipTestscd adminmvn spring-boot:runcd ../webmvn spring-boot:runcd ../xiaomi-store-admin-vuenpm installnpm run servecd ../xiaomi-store-vuenpm installnpm run serve 注意:运行前…...
