当前位置: 首页 > news >正文

13 设计模式之外观模式(家庭影院案例)

一、什么是外观模式?

1.定义

        在日常生活中,许多人喜欢通过遥控器来控制家中的电视、音响、DVD 播放器等设备。虽然这些设备各自独立工作,但遥控器提供了一个简洁的界面,让用户可以轻松地操作多个设备。而这一设计理念正是 外观模式(Facade Pattern) 的核心思想——通过为复杂的子系统提供一个统一的接口,简化客户端与这些子系统的交互。

        外观模式是一种结构型设计模式,旨在为复杂系统中的多个子系统提供一个统一的高层接口,使得客户端可以通过这个接口轻松与各个子系统进行交互,而无需直接处理复杂的实现细节。换句话说,外观模式隐藏了子系统的复杂性,为客户端提供了一个简单的接口。

2.外观模式的关键点:

  • 提供一个高层接口,让客户端通过它与多个子系统交互。
  • 隐藏系统内部的复杂性,简化外部调用。
  • 使得子系统的客户端与子系统之间解耦,降低了系统之间的依赖性。

二、外观模式的应用场景

  • 复杂系统的简化接口:当一个系统包含多个复杂的子系统时,使用外观模式可以将这些复杂的操作封装成一个统一的接口,简化客户端的使用。
  • 系统解耦:如果你不希望系统的客户端直接与各个子系统进行耦合,外观模式提供了一个解耦的方案。通过外观类,客户端不需要了解子系统的内部实现,减少了对系统内部的了解和依赖。

三、外观模式的示例

        接下来,我们通过一个家庭影院系统的例子,来演示外观模式的应用。我们设想有一个家庭影院系统,包含多个设备:电视、音响和 DVD 播放器。每个设备有不同的控制方法,用户需要通过多个操作来启动或关闭它们。为了简化操作,我们可以通过外观模式将这些操作封装成一个统一的接口。

1.设备类

// 电视类
public class TV {public void on() {System.out.println("电视打开了");}public void off() {System.out.println("电视关上了");}
}// 音响类
public class SoundSystem {public void on() {System.out.println("音响开了");}public void off() {System.out.println("音响关了");}
}// DVD 播放器类
public class DVDPlayer {public void on() {System.out.println("DVD 播放器开了");}public void off() {System.out.println("DVD 播放器关了");}public void play() {System.out.println("播放电影...");}public void stop() {System.out.println("停止播放...");}
}

2.外观类:

// 家庭影院外观类
public class HomeTheaterFacade {private TV tv;private SoundSystem soundSystem;private DVDPlayer dvdPlayer;public HomeTheaterFacade(TV tv, SoundSystem soundSystem, DVDPlayer dvdPlayer) {this.tv = tv;this.soundSystem = soundSystem;this.dvdPlayer = dvdPlayer;}// 观看电影public void watchMovie() {tv.on();soundSystem.on();dvdPlayer.on();dvdPlayer.play();System.out.println("电影已经播放");}// 停止电影public void stopMovie() {tv.off();soundSystem.off();dvdPlayer.off();dvdPlayer.stop();System.out.println("电影已经关闭");}
}

3.客户端代码:

// 测试外观模式
public class TestFacade {public static void main(String[] args) {// 创建设备实例TV tv = new TV();SoundSystem soundSystem = new SoundSystem();DVDPlayer dvdPlayer = new DVDPlayer();// 创建家庭影院外观实例HomeTheaterFacade facade = new HomeTheaterFacade(tv, soundSystem, dvdPlayer);// 使用外观类操作设备facade.watchMovie();facade.stopMovie();}
}

4.输出结果

电视打开了
音响开了
DVD 播放器开了
播放电影...
电影已经播放
电视关上了
音响关了
DVD 播放器关了
停止播放...
电影已经关闭


四、外观模式的组成

1.组成部分:

  • 外观类(Facade Class)

    外观类是外观模式的核心,负责定义一个统一的高层接口,提供给客户端调用。它封装了子系统的复杂操作,使得客户端能够通过这个接口与多个子系统进行交互。外观类通常通过组合和调用子系统类来实现对外的简化接口。

  • 子系统类(Subsystem Classes)

    子系统类是一些具体的类,它们实现了系统的业务逻辑。子系统类的职责比较具体,负责实际的功能实现。外观类通过委托的方式,向这些子系统发出请求。子系统类之间通常是彼此独立的,外观类负责协调它们的调用。

  • 客户端(Client)

    客户端通过外观类提供的接口来访问系统。客户端不需要了解子系统类的复杂性,只需要通过外观类进行操作,从而实现对整个系统的控制。

2.组成关系:

  • 外观类:提供一个简单的接口,简化客户端与子系统的交互。
  • 子系统类:实现具体的业务逻辑,但它们不暴露给客户端,客户端通过外观类与它们交互。
  • 客户端:只与外观类交互,通过外观类简化对系统的操作。

3.外观模式的工作流程:

  • 客户端通过外观类提供的简化接口发出请求
  • 外观类负责协调并调用一个或多个子系统类来完成请求
  • 子系统类执行具体的操作,并将结果返回给外观类
  • 外观类将子系统操作的结果返回给客户端

五、外观模式的优缺点:

1.优点:

  • 简化客户端代码:客户端只需要通过外观类提供的简单接口来控制复杂的子系统,而不需要直接操作各个子系统,极大简化了客户端的调用。
  • 解耦:外观模式通过提供一个统一的接口,减少了客户端与子系统之间的依赖,使得客户端与子系统的耦合度降低。
  • 易于扩展:如果将来要添加新的设备(如投影仪、蓝光播放器等),只需要对外观类进行扩展,而不需要修改客户端的代码,符合开放封闭原则。

2.缺点:

  • 外观类可能变得臃肿:如果有大量的子系统,外观类可能会变得非常庞大,承担过多的职责,变成“胖外观类”,这时可以考虑使用多个外观类来分担责任。
  • 隐藏了子系统功能:外观模式的简化接口虽然易于使用,但也隐藏了子系统的一些功能。如果客户端需要更多的控制或者定制化操作,可能就无法通过外观类来实现,必须直接与子系统交互。

六、总结

        外观模式是一种非常实用的设计模式,适用于需要简化复杂系统接口的场景。它通过为复杂的子系统提供一个统一的、高层次的接口,使得客户端能够通过简单的调用来完成复杂的任务。使用外观模式,我们可以提高系统的可维护性、可扩展性,并且让客户端代码更加简洁易懂。

        通过本文的家庭影院系统示例,我们可以看到外观模式如何将多个设备的控制操作集中到一个外观类中,减少了客户端的操作复杂度。如果你在实际项目中遇到类似的情况,可以考虑使用外观模式来简化系统的操作接口。 


        希望这篇文章能帮助你理解外观模式的应用和实现!如果你有任何问题,或者希望进一步探讨其他设计模式,欢迎随时联系我!

相关文章:

13 设计模式之外观模式(家庭影院案例)

一、什么是外观模式? 1.定义 在日常生活中,许多人喜欢通过遥控器来控制家中的电视、音响、DVD 播放器等设备。虽然这些设备各自独立工作,但遥控器提供了一个简洁的界面,让用户可以轻松地操作多个设备。而这一设计理念正是 外观模…...

单片机学习笔记 12. 定时/计数器_定时

更多单片机学习笔记:单片机学习笔记 1. 点亮一个LED灯单片机学习笔记 2. LED灯闪烁单片机学习笔记 3. LED灯流水灯单片机学习笔记 4. 蜂鸣器滴~滴~滴~单片机学习笔记 5. 数码管静态显示单片机学习笔记 6. 数码管动态显示单片机学习笔记 7. 独立键盘单片机学习笔记 8…...

Web安全基础实践

实践目标 (1)理解常用网络攻击技术的基本原理。(2)Webgoat实践下相关实验。 WebGoat WebGoat是由著名的OWASP负责维护的一个漏洞百出的J2EE Web应用程序,这些漏洞并非程序中的bug,而是故意设计用来讲授We…...

Zookeeper集群数据是如何同步的?

大家好,我是锋哥。今天分享关于【Zookeeper集群数据是如何同步的?】面试题。希望对大家有帮助; Zookeeper集群数据是如何同步的? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Zookeeper集群中的数据同步是通过一种称为ZAB(Zo…...

SpringCloud框架学习(第六部分:Sentinel实现熔断与限流)

目录 十四、SpringCloud Alibaba Sentinel实现熔断与限流 1.简介 2.作用 3.下载安装 4.微服务 8401 整合 Sentinel 入门案例 5.流控规则 (1)基本介绍 (2)流控模式 Ⅰ. 直接 Ⅱ. 关联 Ⅲ. 链路 (3&#xff0…...

动态规划-----路径问题

动态规划-----路径问题 下降最小路径和1:状态表示2:状态转移方程3 初始化4 填表顺序5 返回值6 代码实现 总结: 下降最小路径和 1:状态表示 假设:用dp[i][j]表示:到达[i,j]的最小路径 2:状态转…...

Rust循环引用与多线程并发

循环引用与自引用 循环引用的概念 循环引用指的是两个或多个对象之间相互持有对方的引用。在 Rust 中&#xff0c;由于所有权和生命周期的严格约束&#xff0c;直接创建循环引用通常会导致编译失败。例如&#xff1a; // 错误的循环引用示例 struct Node {next: Option<B…...

东方隐侠网安瞭望台第8期

谷歌应用商店贷款应用中的 SpyLoan 恶意软件影响 800 万安卓用户 迈克菲实验室的新研究发现&#xff0c;谷歌应用商店中有十多个恶意安卓应用被下载量总计超过 800 万次&#xff0c;这些应用包含名为 SpyLoan 的恶意软件。安全研究员费尔南多・鲁伊斯上周发布的分析报告称&…...

底部导航栏新增功能按键

场景需求&#xff1a; 在底部导航栏添加power案件&#xff0c;单击息屏&#xff0c;长按 关机 如下实现图 借此需求&#xff0c;需要掌握技能&#xff1a; 底部导航栏如何实现新增、修改、删除底部导航栏流程对底部导航栏部分样式如何修改。 比如放不下、顺序排列、坑点如…...

C++ 之弦上舞:string 类与多样字符串操作的优雅旋律

string 类的重要性及与 C 语言字符串对比 在 C 语言中&#xff0c;字符串是以 \0 结尾的字符集合&#xff0c;操作字符串需借助 C 标准库的 str 系列函数&#xff0c;但这些函数与字符串分离&#xff0c;不符合 OOP 思想&#xff0c;且底层空间管理易出错。而在 C 中&#xff0…...

centos8:Could not resolve host: mirrorlist.centos.org

【1】错误消息&#xff1a; [rootcentos211 redis-7.0.15]# yum update CentOS Stream 8 - AppStream …...

Linux 定时任务 命令解释 定时任务格式详解

目录 时间命令 修改时间和日期 定时任务格式 定时任务执行 查看定时任务进程 重启定时任务 时间命令 #查看时间 [rootlocalhost ~]# date 2021年 07月 23日 星期五 14:38:19 CST --------------------------------------- [rootlocalhost ~]# date %F 2021-07-23 -----…...

aws(学习笔记第十五课) 如何从灾难中恢复(recover)

aws(学习笔记第十五课) 如何从灾难中恢复 学习内容&#xff1a; 使用CloudWatch对服务器进行监视与恢复区域(region)&#xff0c;可用区(available zone)和子网(subnet)使用自动扩展(AutoScalingGroup) 1. 使用CloudWatch对服务器进行监视与恢复 整体架构 这里模拟Jenkins Se…...

github webhooks 实现网站自动更新

本文目录 Github Webhooks 介绍Webhooks 工作原理配置与验证应用云服务器通过 Webhook 自动部署网站实现复制私钥编写 webhook 接口Github 仓库配置 webhook以服务的形式运行 app.py Github Webhooks 介绍 Webhooks是GitHub提供的一种通知方式&#xff0c;当GitHub上发生特定事…...

【C语言】递归的内存占用过程

递归 递归是函数调用自身的一种编程技术。在C语言中&#xff0c;递归的实现会占用内存栈&#xff08;Call Stack&#xff09;&#xff0c;每次递归调用都会在栈上分配一个新的 “栈帧&#xff08;Stack Frame&#xff09;”&#xff0c;用于存储本次调用的函数局部变量、返回地…...

365天深度学习训练营-第P6周:VGG-16算法-Pytorch实现人脸识别

&#x1f368; 本文为&#x1f517;365天深度学习训练营中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 文为「365天深度学习训练营」内部文章 参考本文所写记录性文章&#xff0c;请在文章开头带上「&#x1f449;声明」 &#x1f37a;要求&#xff1a; 保存训练过…...

企业AI助理在数据分析与决策中扮演的角色

在当今这个数据驱动的时代&#xff0c;企业每天都需要处理和分析大量的数据&#xff0c;以支持其业务决策。然而&#xff0c;面对如此庞大的数据量&#xff0c;传统的数据分析方法已经显得力不从心。幸运的是&#xff0c;随着人工智能&#xff08;AI&#xff09;技术的不断发展…...

洛谷 B2029:大象喝水 ← 圆柱体体积

【题目来源】https://www.luogu.com.cn/problem/B2029【题目描述】 一只大象口渴了&#xff0c;要喝 20 升水才能解渴&#xff0c;但现在只有一个深 h 厘米&#xff0c;底面半径为 r 厘米的小圆桶 &#xff08;h 和 r 都是整数&#xff09;。问大象至少要喝多少桶水才会解渴。 …...

go每日一题:mock打桩、defer、recovery、panic的调用顺序

题目一&#xff1a;单元测试中使用—打桩 打桩概念&#xff1a;使用A替换 原函数B&#xff0c;那么A就是打桩函数打桩原理&#xff1a;运行时&#xff0c;通过一个包&#xff0c;将内存中函数的地址替换为桩函数的地址打桩操作&#xff1a;利用Patch&#xff08;&#xff09;函…...

STM32F103 HSE时钟倍频以及设置频率函数(新手向,本人也是新手)

HSE_SetSysCLK是野火教程里的,不懂的去这 16-RCC&#xff08;第3节&#xff09;使用HSE配置系统时钟并使用MCO输出监控系统时钟_哔哩哔哩_bilibili HSE_AutoSetHSE的算法部分是自己写的,用了一个转接数组。C语言不支持bool所以自己定义了一个boolK代替bool。 AutoHSE.h: /**…...

【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15

缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下&#xff1a; struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

CTF show Web 红包题第六弹

提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框&#xff0c;很难让人不联想到SQL注入&#xff0c;但提示都说了不是SQL注入&#xff0c;所以就不往这方面想了 ​ 先查看一下网页源码&#xff0c;发现一段JavaScript代码&#xff0c;有一个关键类ctfs…...

反向工程与模型迁移:打造未来商品详情API的可持续创新体系

在电商行业蓬勃发展的当下&#xff0c;商品详情API作为连接电商平台与开发者、商家及用户的关键纽带&#xff0c;其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息&#xff08;如名称、价格、库存等&#xff09;的获取与展示&#xff0c;已难以满足市场对个性化、智能…...

React Native 导航系统实战(React Navigation)

导航系统实战&#xff08;React Navigation&#xff09; React Navigation 是 React Native 应用中最常用的导航库之一&#xff0c;它提供了多种导航模式&#xff0c;如堆栈导航&#xff08;Stack Navigator&#xff09;、标签导航&#xff08;Tab Navigator&#xff09;和抽屉…...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径&#xff0c; 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解&#xff0c;但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后&#xff0c;通常在该文件中会出现以下配置&…...

基于Uniapp开发HarmonyOS 5.0旅游应用技术实践

一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架&#xff0c;支持"一次开发&#xff0c;多端部署"&#xff0c;可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务&#xff0c;为旅游应用带来&#xf…...

vue3 字体颜色设置的多种方式

在Vue 3中设置字体颜色可以通过多种方式实现&#xff0c;这取决于你是想在组件内部直接设置&#xff0c;还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法&#xff1a; 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南

文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/55aefaea8a9f477e86d065227851fe3d.pn…...

什么是Ansible Jinja2

理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具&#xff0c;可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板&#xff0c;允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板&#xff0c;并通…...

Java求职者面试指南:计算机基础与源码原理深度解析

Java求职者面试指南&#xff1a;计算机基础与源码原理深度解析 第一轮提问&#xff1a;基础概念问题 1. 请解释什么是进程和线程的区别&#xff1f; 面试官&#xff1a;进程是程序的一次执行过程&#xff0c;是系统进行资源分配和调度的基本单位&#xff1b;而线程是进程中的…...