设计模式 10 外观模式

news/2024/9/18 14:53:15/ 标签: 设计模式, 外观模式

设计模式 10

  • 创建型模式(5):工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式
  • 结构型模式(7):适配器模式、桥接模式、组合模式、装饰者模式、外观模式、享元模式、代理模式
  • 行为型模式(11):责任链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式、访问者模式

文章目录

  • 设计模式 10
    • 外观模式(Facade Pattern)
      • 1 定义
      • 2 结构
      • 3 示例代码
      • 4 特点
      • 5 适用场景
      • 6 与其他模式的关系

外观模式(Facade Pattern)

1 定义

外观模式通过为复杂的子系统提供一个简化的接口,使得客户端可以通过这个接口访问子系统的功能,而不需要直接与子系统的多个组件进行交互。外观模式可以隐藏子系统的复杂性,并且使得子系统与客户端的耦合度降低。

2 结构

外观模式的结构包含以下角色:

  • 外观(Facade): 提供一个简化的接口,封装子系统的复杂性,供客户端调用。
  • 子系统(Subsystem Classes): 子系统中的多个类,它们实现了子系统的实际功能。子系统可以有多个类,客户端可以直接访问它们,但通过外观类访问会更简单。

UML 类图

                            +-------------------+|      Client       |+-------------------+^|
+-------------------+       +-------------------+       +-------------------+
|    SubsystemA     | ----> |      Facade       | <---- |    SubsystemC     |
+-------------------+       +-------------------+       +-------------------+^                           ^|                           |+-------------------+       +-------------------+|    SubsystemB     |       |    SubsystemD     |+-------------------+       +-------------------+

3 示例代码

以下是一个实现外观模式的简单示例。在这个示例中,我们构建了一个家庭影院系统,客户端通过外观类 HomeTheaterFacade 来控制各个子系统,如电视、音响、灯光等。

子系统类

// 子系统类:电视
public class Television
{public void On(){Console.WriteLine("Television is on.");}public void Off(){Console.WriteLine("Television is off.");}
}// 子系统类:音响
public class SoundSystem
{public void On(){Console.WriteLine("Sound system is on.");}public void Off(){Console.WriteLine("Sound system is off.");}public void SetVolume(int volume){Console.WriteLine($"Sound system volume set to {volume}.");}
}// 子系统类:灯光
public class Lights
{public void Dim(int level){Console.WriteLine($"Lights dimmed to {level}%.");}public void On(){Console.WriteLine("Lights are on.");}
}

外观类

// 外观类:家庭影院
public class HomeTheaterFacade
{private readonly Television _television;private readonly SoundSystem _soundSystem;private readonly Lights _lights;public HomeTheaterFacade(Television television, SoundSystem soundSystem, Lights lights){_television = television;_soundSystem = soundSystem;_lights = lights;}public void WatchMovie(){Console.WriteLine("Get ready to watch a movie...");_lights.Dim(30);_television.On();_soundSystem.On();_soundSystem.SetVolume(5);}public void EndMovie(){Console.WriteLine("Shutting movie theater down...");_television.Off();_soundSystem.Off();_lights.On();}
}

客户端代码

class Program
{static void Main(string[] args){// 创建子系统对象Television television = new Television();SoundSystem soundSystem = new SoundSystem();Lights lights = new Lights();// 创建外观对象HomeTheaterFacade homeTheater = new HomeTheaterFacade(television, soundSystem, lights);// 使用外观模式控制子系统homeTheater.WatchMovie();Console.WriteLine("\nMovie is running...\n");homeTheater.EndMovie();}
}

在这个例子中:

  • TelevisionSoundSystemLights 是子系统类,提供了各自的功能。
  • HomeTheaterFacade 是外观类,它将各个子系统的操作封装成了 WatchMovie()EndMovie() 两个简单的方法,客户端只需调用这些方法即可控制整个家庭影院系统。
  • 客户端 Program 通过 HomeTheaterFacade 类来控制整个家庭影院的各个设备,而不需要直接与每个设备交互。

4 特点

  • 优点:

    • 简化接口: 提供一个简化的接口来访问复杂的子系统,减少客户端与子系统之间的耦合。

    • 隐藏子系统的复杂性: 客户端不需要了解子系统的内部结构,只需要与外观类交互即可。

    • 减少依赖: 客户端与子系统之间的依赖关系减少,如果子系统发生变化,只需修改外观类,而不需要修改客户端代码。

  • 缺点:

    • 不符合开闭原则: 如果要扩展外观类的功能,可能需要修改外观类的代码,从而违反开闭原则。

    • 潜在性能问题: 外观模式可能会因为封装了大量子系统的调用,而引入一定的性能开销。

5 适用场景

  • 简化复杂系统的使用: 当系统内部结构复杂,客户端希望能够通过简单的接口使用系统时,使用外观模式非常合适。
  • 解耦客户端与子系统: 当你希望减少客户端与多个子系统之间的依赖关系时,可以使用外观模式
  • 构建库或框架: 当你构建一个复杂库或框架,并希望提供一个简洁的接口供外部使用时,外观模式可以帮助你设计这个接口。

6 与其他模式的关系

  • 与适配器模式的区别: 适配器模式是为了将一个接口转换为客户端期望的接口,而外观模式是为了提供一个简化的接口来使用复杂系统。适配器模式专注于接口兼容性,而外观模式专注于简化系统的使用。
  • 与桥接模式的区别: 桥接模式用于将抽象与实现分离,使得它们可以独立变化,而外观模式关注于简化接口。
  • 与单例模式的结合: 在某些情况下,外观类可以设计成单例,以确保客户端使用的是同一个外观对象。

外观模式通过提供一个统一和简化的接口来隐藏系统的复杂性,使得客户端能够更轻松地使用系统,同时保持系统内部结构的灵活性和可扩展性。


http://www.ppmy.cn/news/1517032.html

相关文章

ansible的tags标签

1、tags模块 可以给任务定义标签&#xff0c;可以根据标签来运行指定的任务 2、标签的类型 always&#xff1a;设定了标签名为always&#xff0c;除非指定跳过这个标签&#xff0c;否则该任务将始终会运行&#xff0c;即使指定了标签还会运行never&#xff1a;始终不运行的任…

CPU、MPU、MCU、SOC分别是什么?

CPU、MPU、MCU和SoC都是与微电子和计算机科学相关的术语&#xff0c;它们在功能定位、应用场景以及处理能力等方面有所区别。具体如下&#xff1a; CPU&#xff1a;CPU是中央处理单元的缩写&#xff0c;它通常指计算机内部负责执行程序指令的芯片。CPU是所有类型计算机&#x…

java 读取mysql中的表并按照指定格式导出excel

在Java中读取MySQL中的数据表并将其导出到Excel文件中&#xff0c;你需要以下几个步骤&#xff1a; 连接MySQL数据库&#xff1a;使用JDBC驱动程序连接到MySQL数据库。执行SQL查询&#xff1a;获取表数据。使用Apache POI库生成Excel文件&#xff1a;将数据写入Excel格式。保存…

SpringBoot文档之构建包的阅读笔记

Packaging Spring Boot Applications Efficient Deployments Efficient Deployments 默认情况下&#xff0c;基于SpringBoot框架开发应用时&#xff0c;构建插件spring-boot-maven-plugin将项目打包为fat jar。 执行如下命令&#xff0c;解压构建得到的jar文件。 java -Djarmo…

Python 程序设计基础教程

Python 程序设计基础教程 撰稿人&#xff1a;南星六月雪 第 一 章 变量与简单数据类型 1.1 变量 先来观察以下程序&#xff1a; world "Hello Python!" print(world)world "Hello Python,I love you!" print(world)运行这个程序&#xff0c;将看到两…

0827作业+梳理(c++day01)

一、作业&#xff1a; 1、代码 #include <iostream> using namespace std; int main() {string str;cout<<"请输入一个字符串"<<endl;getline(cin,str);cout<<"str "<<str<<endl;//初始化各类字符个数int size_num …

如何保证Redis与数据库之间的一致性

在现代应用程序架构中&#xff0c;Redis等内存数据库因其高性能和低延迟特性而被广泛用于缓存、会话管理、消息队列等多种场景。然而&#xff0c;当Redis作为数据库&#xff08;如MySQL、PostgreSQL&#xff09;的缓存层时&#xff0c;确保数据在Redis和数据库之间的一致性变得…

jmeter中CSV 数据文件设置用例

1、CSV数据文件的基础使用 线程组->添加->配置远近->CSV数据文件设置 2、多条用例运行CSV数据文件 由于我的csv请求的json数据有“&#xff0c;”所以我这边 分隔符选择了*号 写了两行需要测试的用例&#xff0c;需要添加一个“循环控制器” 线程组->添加-&g…

splunk Enterprise 的HTTP收集器-windows

1.创建HTTP收集器 2.使用HTTP收集器 然后打开全局设置&#xff1a;把ssl给去掉&#xff0c;点保存&#xff08;保存之后&#xff0c;可以看到这些状态全部都是已启用了&#xff09;&#xff1a; 3.测试&#xff1a; curl --location --request POST http://192.168.11.131:808…

List<String> 和 ArrayList<String>的区别

List<String> list new ArrayList<>() 这种形式实际上是一种向上转型&#xff08;upcasting&#xff09;的体现&#xff0c;ArrayList 实现了 List 接口&#xff0c;可以看成是从 List 继承而来&#xff0c;一个子类的对象可以指向它父类。 为什么不是 ArrayList…

国标GB28181视频监控EasyCVR视频汇聚平台国标注册被陌生IP入侵如何处理?

GB28181国标/GA/T1400协议/安防综合管理系统EasyCVR视频汇聚平台能在复杂的网络环境中&#xff0c;将前端设备统一集中接入与汇聚管理。智慧安防/视频存储/视频监控/视频汇聚EasyCVR平台可以提供实时远程视频监控、视频录像、录像回放与存储、告警、语音对讲、云台控制、平台级…

Leetcode 78 子集 回溯 C++实现

Leetcode 78. 子集 问题&#xff1a;给你一个整数数组 nums &#xff0c;数组中的元素 互不相同 。返回该数组所有可能的子集&#xff08;幂集&#xff09;。解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 方法1&#xff1a; 创建返回二维数组 ans &#xff0c;和…

★ 算法OJ题 ★ 力扣283 - 移动零

Ciallo&#xff5e;(∠・ω< )⌒☆ ~ 今天&#xff0c;我将和大家一起做一道双指针算法题--移动零~ 目录 一 题目 二 算法解析 三 编写算法 一 题目 283. 移动零 - 力扣&#xff08;LeetCode&#xff09;链接&#xff1a;283. 移动零 - 力扣&#xff08;LeetCode&am…

linux 安装kafaka单体服务

1.下载kafka的linux安装包 前往Apache Kafka官方网站下载页面&#xff08;Apache Kafkahttps://kafka.apache.org/downloads&#xff09;&#xff0c;选择最新稳定版的Kafka二进制分发文件&#xff0c;通常是以.tgz结尾的文件。 手动下载kafka_2.13-3.8.0.tgz到本地&#xff0…

[图论]游戏

题目描述 B B B 经常与 A A A 一起玩游戏。今天&#xff0c;他们在一棵树上玩游戏。 A A A 有 m 1 m1 m1 块石子&#xff0c; B B B 有 m 2 m2 m2 块石子&#xff0c;游戏一开始&#xff0c;所有石头放在树的节点处&#xff0c;除了树根。 A A A 先移动石子。然后两人轮流移…

Java学习Day31:HTML 第一章:观音禅院

1.结构介绍 1.标签的分类 <单词> &#xff1a;元素标签 <元素 单词>&#xff1a;首先<>中至少有两个单词&#xff0c;那第一个肯定是元素标签&#xff0c;元素标签后跟的都是属性标签 2.文本元素 段落元素 段落元素 换行标签 br 水平线标签 标签会在页面…

【石子合并】

题目 错解 #include <bits/stdc.h> using namespace std; const int N 310; int a[N], s[N], f[N][N]; int main() {int n;cin >> n;memset(f, 0x3f, sizeof f);for(int i 1; i < n; i){cin >> a[i];s[i] s[i-1] a[i];f[i][i] 0;}for(int i 1; i &…

Datawhale X 李宏毅苹果书 AI夏令营-深度学习基础-Task1

# Datawhale AI 夏令营 夏令营手册&#xff1a;向李宏毅学深度学习 深度学习临界点 临界点&#xff1a;梯度为零的点 在神经网络训练过程中&#xff0c;当参数对损失微分为零的时候&#xff0c;梯度下降就不能再更新参数了&#xff0c;训练就停下来了&#xff0c;损失不再下…

Linux信号处理机制基础

什么是信号 信号在最早的UNIX系统中即被引入&#xff0c;已有30多年的历史&#xff0c;但只有很小的变化。信号是提供异步事件处理机制的软件中断。进程之间可以相互发送信号&#xff0c;这使信号成为一种进程间通信(Inter-ProcessCommunication,lPC)的基本手段 信号的名称与…

论文翻译:Multi-step Jailbreaking Privacy Attacks on ChatGPT

Multi-step Jailbreaking Privacy Attacks on ChatGPT https://arxiv.org/pdf/2304.05197 多步骤越狱隐私攻击对ChatGPT的影响 文章目录 多步骤越狱隐私攻击对ChatGPT的影响摘要1 引言2 相关工作3 对ChatGPT的数据提取攻击3.1 数据收集3.2 攻击制定3.3 从ChatGPT中提取私人数据…