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.缺点:

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

六、总结

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

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


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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/482569.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

文件比较和文件流

文件比较和文件流 一、文本比较工具 diff1.基本用法1.1输出格式 2.常用选项 二、文件流1.文件的打开模式2.文件流的分类ifstreamofstreamfstrem区别 3.文件流的函数1. 构造函数2. is_open 用于判断文件是否打开3. open4. getline5. close6. get()7. read8. write9. put10. gcou…

《如何使用Unity的Avatar人偶以及启动重定向-实现2个或多个人物模型使用同一个动画片段》

8.5 使用Avatar和人物重定向 注意事项: 这个人偶以及重定向技术只能作用于人物模型! 这个人偶以及重定向技术只能作用于人物模型! 这个人偶以及重定向技术只能作用于人物模型! 1. 基本原理 在Unity中,Avatar人偶和…

windows 应用 UI 自动化实战

UI 自动化技术架构选型 UI 自动化是软件测试过程中的重要一环,网络上也有很多 UI 自动化相关的知识或资料,具体到 windows 端的 UI 自动化,我们需要从以下几个方面考虑: 开发语言 毋庸置疑,在 UI 自动化测试领域&am…

百度 文心一言 vs 阿里 通义千问 哪个好?

背景介绍: 在当前的人工智能领域,随着大模型技术的快速发展,市场上涌现出了众多的大规模语言模型。然而,由于缺乏统一且权威的评估标准,很多关于这些模型能力的文章往往基于主观测试或自行设定的排行榜来评价模型性能…

基于协同推荐的黔醉酒业白酒销售系统

文末获取源码和万字论文 摘 要 基于协同推荐的黔醉酒业白酒销售系统主要针对黔醉酒业的具体业务需求所设计,现阶段阶段我国大型企业都会有自己的电商平台以及销售管理系统,其功能对于中小型过于冗长复杂,成本也不是中小型企业能够承受的&…

解决jupyter notebook 新建或打开.ipynb 报500 : Internal Server Error(涉及jinja2兼容性问题)

报错: [E 10:09:52.362 NotebookApp] 500 GET /notebooks/Untitled16.ipynb?kernel_namepyt hon3 (::1) 93.000000ms refererhttp://localhost:8888/tree ...... 重点是: from .exporters import * File "C:\ProgramData\Anaconda3\lib\site-p…

Kali Linux系统一键汉化中文版及基础使用详细教程

Kali Linux系统一键汉化中文版及基础使用详细教程 引言 Kali Linux是一款基于Debian的Linux发行版,专为渗透测试和网络安全而设计。由于其强大的功能和丰富的工具,Kali Linux在安全领域得到了广泛应用。然而,许多用户在使用Kali Linux时会遇…

LLaMA-Factory 上手即用教程

LLaMA-Factory 是一个高效的大型语言模型微调工具,支持多种模型和训练方法,包括预训练、监督微调、强化学习等,同时提供量化技术和实验监控,旨在提高训练速度和模型性能。 官方开源地址:https://github.com/hiyouga/L…

使用PyQt5开发一个GUI程序的实例演示

一、安装Python 下载安装到这个目录 G:\Python38-32 安装完成有这些工具,后面备用: G:\Python38-32\Scripts\pyrcc5.exe G:\Python38-32\Scripts\pyuic5.exe 二、PyQt环境配置 pip install PyQt5 pip install pyqt5-tools 建议使用国内源&#xff0c…

【开源免费】基于Vue和SpringBoot的校园资料分享平台(附论文)

博主说明:本文项目编号 T 059 ,文末自助获取源码 \color{red}{T059,文末自助获取源码} T059,文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析…

LocalDateTime序列化(跟redis有关)

使用过 没成功,序列化后是[2024 11 10 17 22 20]差不多是这样, 反序列化后就是: [ 2024 11 10.... ] 可能是我漏了什么 这是序列化后的: 反序列化后: 方法(加序列化和反序列化注解)&…

32 从前序与中序遍历序列构造二叉树

32 从前序与中序遍历序列构造二叉树 32.1 从前序与中序遍历序列构造二叉树解决方案 class Solution { public:TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {return buildTreeHelper(preorder, inorder, 0, 0, inorder.size() - 1)…

【韩顺平老师Java反射笔记】

反射 文章目录 基本使用反射机制java程序在计算机有三个阶段反射相关的主要类 反射调用优化Class类的常用方法获取Class对象的6种方式哪些类型有Class对象类加载类加载时机类加载过程图 通过反射获取类的结构信息第一组&#xff1a;java.lang.Class类第二组&#xff1a;java.la…

Python实现2048小游戏

2048是一个单人益智游戏&#xff0c;目标是移动和合并数字&#xff0c;以达到2048。 1. 实现效果 Python实现2048小游戏 2. 游戏规则 简单地理解一下规则 基本规则&#xff1a; 4x4棋盘&#xff0c;每个格可包含一个2的倍数的数字&#xff0c;初始时为空&#xff0c;表示0。…

基于树莓派3B+的简易智能家居小项目(WiringPi库 + C语言开发)

github主页&#xff1a;https://github.com/snqx-lqh 本项目github地址&#xff1a;https://github.com/snqx-lqh/RaspberryPiSmartHome 硬件开源地址&#xff1a;https://oshwhub.com/from_zero/shu-mei-pai-kuo-zhan-ban 欢迎交流 树莓派智能家居项目&#xff0c;学习树莓派的…

MacOS安装MySQL数据库和Java环境以及Navicat

安装MySQL 去官网下载&#xff1a;MySQL 下载好后安装&#xff0c;在设置里往下滑&#xff0c;出现了这样&#xff0c;就代表安装成功了 接下来配置环境&#xff1a; 首先在我们的设备上找到终端并打开,输入 vim ~/.bash_profile(注意vim后面的空格)&#xff0c;输入完成后点击…

【论文笔记】Towards Online Continuous Sign Language Recognition and Translation

&#x1f34e;个人主页&#xff1a;小嗷犬的个人主页 &#x1f34a;个人网站&#xff1a;小嗷犬的技术小站 &#x1f96d;个人信条&#xff1a;为天地立心&#xff0c;为生民立命&#xff0c;为往圣继绝学&#xff0c;为万世开太平。 基本信息 标题: Towards Online Continuou…

手机控制载货汽车一键启动无钥匙进入广泛应用

移动管家载货汽车一键启动无钥匙进入手机控车系统‌&#xff0c; 该系统广泛应用于物流运输、工程作业等货车场景&#xff0c;为车主提供了高效、便捷的启动和熄火解决方案&#xff0c;体现了科技进步对物流行业的积极影响‌ 核心功能‌&#xff1a;简化启动流程&#xff0c;提…

「Mac畅玩鸿蒙与硬件34」UI互动应用篇11 - 颜色选择器

本篇将带你实现一个颜色选择器应用。用户可以从预设颜色中选择&#xff0c;或者通过输入颜色代码自定义颜色来动态更改界面背景。该应用展示了如何结合用户输入、状态管理和界面动态更新的功能。 关键词 UI互动应用颜色选择器状态管理用户输入界面动态更新 一、功能说明 颜色…

【解决安全扫描漏洞】---- 检测到目标站点存在 JavaScript 框架库漏洞

1. 漏洞结果 JavaScript 框架或库是一组能轻松生成跨浏览器兼容的 JavaScript 代码的工具和函数。如果网站使用了存在漏洞的 JavaScript 框架或库&#xff0c;攻击者就可以利用此漏洞来劫持用户浏览器&#xff0c;进行挂马、XSS、Cookie劫持等攻击。 1.1 漏洞扫描截图 1.2 具体…