设计模式之外观模式(Facade)

news2024/9/22 21:15:35

Facade设计模式,也称为外观模式,是一种结构型设计模式,它主要用于为子系统中的一组接口提供一个统一的高层接口,从而使得子系统更加容易使用。以下是关于Facade设计模式的详细介绍:

一、定义

Facade模式为多个复杂的子系统提供一个对外的接口,使得这些子系统更加容易地被访问。该模式对外有一个统一的接口,外部应用无需关心子系统内部的细节,从而大大降低了应用程序的复杂度,提高了可维护性。

二、动机与目的

  • 降低复杂性:通过将子系统的复杂性封装在Facade类中,客户端可以通过简单的接口来调用子系统,而无需深入了解子系统的具体实现。
  • 提高易用性:Facade模式提供了一个简单的接口,使得客户端可以更容易地使用子系统。
  • 松散耦合:通过引入Facade类,降低了客户端与子系统之间的耦合度,使得子系统内部的变化不会影响到客户端。

三、结构与类图

类图:

Facade模式主要包含以下三个角色:

  • Facade(外观角色):客户端可以调用这个角色的方法。外观类知晓相关的(一个或者多个)子系统的功能和责任。在正常情况下,本角色会将所有从客户端发来的请求委派到相应的子系统去。
  • Subsystem(子系统角色):可以同时有一个或者多个子系统。每一个子系统都不是一个单独的类,而是一个类的集合。每一个子系统都可以被客户端直接调用,或者被外观角色调用。子系统并不知道外观的存在,对于子系统而言,外观仅仅是另外一个客户端而已。
  • Client(客户端角色):用户通过外观类调用子系统的功能。

四、优缺点

优点
  1. 降低系统的复杂性:通过为子系统提供一个简单的接口,使得客户端更容易理解和使用系统。
  2. 提高系统的灵活性:当子系统内部发生变化时,只需要修改Facade类即可,而不需要修改客户端代码。
  3. 符合迪米特法则:通过引入Facade类,减少了客户端与子系统之间的依赖关系。
缺点
  1. 增加子系统或扩展子系统行为容易引入风险:因为所有的请求都需要通过Facade类进行转发,如果Facade类设计不当,可能会引入新的风险。
  2. 不符合开闭原则:在某些情况下,如果需要对系统进行扩展,可能需要修改Facade类的代码,这违反了开闭原则(即对扩展开放,对修改关闭)。

五、应用场景

  • 当系统需要对外提供一个简单的接口时,可以使用Facade模式。
  • 当系统需要隐藏子系统的复杂性时,可以使用Facade模式。
  • 当需要构建一个多层系统结构时,可以利用Facade对象作为每层的入口,简化层级调用。

六、实现例子

在家庭影院系统中,可以使用Facade模式来简化用户的操作。例如,用户只需要使用一个遥控器(Facade类)就可以控制投影仪、音响、DVD机等设备(子系统),而无需分别操作这些设备。

// 投影仪接口  
interface Projector {  
    void on();  
    void off();  
    void focus();  
    void wideScreenMode();  
}  
  
// 投影仪实现类  
class SimpleProjector implements Projector {  
    @Override  
    public void on() {  
        System.out.println("Projector is on");  
    }  
  
    @Override  
    public void off() {  
        System.out.println("Projector is off");  
    }  
  
    @Override  
    public void focus() {  
        System.out.println("Adjusting projector focus");  
    }  
  
    @Override  
    public void wideScreenMode() {  
        System.out.println("Switching to wide screen mode");  
    }  
}  
  
// DVD播放器接口  
interface DVDPlayer {  
    void on();  
    void off();  
    void play();  
    void stop();  
    void pause();  
    void eject();  
    void setTwoChannelAudio();  
    void setSurroundAudio();  
}  
  
// DVD播放器实现类  
class SimpleDVDPlayer implements DVDPlayer {  
    @Override  
    public void on() {  
        System.out.println("DVD Player is on");  
    }  
  
    @Override  
    public void off() {  
        System.out.println("DVD Player is off");  
    }  
  
    @Override  
    public void play() {  
        System.out.println("DVD Player is playing");  
    }  
  
    @Override  
    public void stop() {  
        System.out.println("DVD Player stopped");  
    }  
  
    @Override  
    public void pause() {  
        System.out.println("DVD Player paused");  
    }  
  
    @Override  
    public void eject() {  
        System.out.println("DVD ejected");  
    }  
  
    @Override  
    public void setTwoChannelAudio() {  
        System.out.println("Stereo mode is on");  
    }  
  
    @Override  
    public void setSurroundAudio() {  
        System.out.println("Surround sound mode is on");  
    }  
}  
  
// 音响接口  
interface Amplifier {  
    void on();  
    void off();  
    void setStereoSound();  
    void setSurroundSound();  
    void setVolume(int volume);  
}  
  
// 音响实现类  
class StereoAmplifier implements Amplifier {  
    @Override  
    public void on() {  
        System.out.println("Amplifier is on");  
    }  
  
    @Override  
    public void off() {  
        System.out.println("Amplifier is off");  
    }  
  
    @Override  
    public void setStereoSound() {  
        System.out.println("Stereo mode is on");  
    }  
  
    @Override  
    public void setSurroundSound() {  
        System.out.println("Surround sound mode is on");  
    }  
  
    @Override  
    public void setVolume(int volume) {  
        System.out.println("Setting volume to " + volume);  
    }  
}  
  
// 家庭影院Facade类  
class HomeTheaterFacade {  
    private Projector projector;  
    private DVDPlayer dvdPlayer;  
    private Amplifier amplifier;  
  
    public HomeTheaterFacade(Projector projector, DVDPlayer dvdPlayer, Amplifier amplifier) {  
        this.projector = projector;  
        this.dvdPlayer = dvdPlayer;  
        this.amplifier = amplifier;  
    }  
  
    // 提供一个简单的方法来观看电影  
    public void watchMovie(String movie) {  
        System.out.println("Get ready to watch a movie...");  
  
        projector.on();  
        projector.wideScreenMode();  
  
        amplifier.on();  
        amplifier.setSurroundSound();  
        amplifier.setVolume(5);  
  
        dvdPlayer.on();  
        dvdPlayer.play(movie);  
  
        System.out.println("Enjoy the movie...");  
    }  
  
    // 提供一个简单的方法来结束观看  
    public void endMovie() {  
        System.out.println("Shutting movie theater down...");  
  
        projector.off();  
        amplifier.off();  
        dvdPlayer.stop();  
        dvdPlayer.eject();  
        dvdPlayer.off();
    }
}
        
class Client{
    public static void main(String[] args) { 
        Projector projector = new SimpleProjector();
        DVDPlayer dvdPlayer = new SimpleDVDPlayer();
        Amplifier amplifier = new StereoAmplifier();
        HomeTheaterFacade homeTheaterFacade = new HomeTheaterFacade(projector,dvdPlayer,amplifier);
        homeTheaterFacade.watchMovie("肖申克的救赎");
        homeTheaterFacade.endMovie();
    }
}

这个例子中可以看到facade模式,特别适用于使用多个组件,组装固定流程,降低客户端的调用复杂度。

七、总结

Facade设计模式是一种非常实用的设计模式,它通过为子系统提供一个统一的接口来降低系统的复杂性、提高系统的易用性和灵活性。然而,在使用该模式时也需要注意其可能带来的缺点和风险。

如果这个模式对你有用,记得点赞收藏。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

TTT架构超越Transformer,ML模型替代RNN隐藏状态!

目录 01 算法原理 02 骨干架构 03 实验结果 一种崭新的大语言模型(LLM)架构有望取代当前主导 AI 领域的 Transformer,并在性能上超越 Mamba。 论文地址:https://arxiv.org/abs/2407.04620 本周一,关于 Test-Time Tr…

ur5e机械臂末端添加dh_ag95夹爪(ubuntu20.04+ROSnoetic)

一、从官网上下载UR5e机械臂 mkdir -p catkin_ws cd catkin_ws git clone https://github.com/UniversalRobots/Universal_Robots_ROS_Driver.git src/Universal_Robots_ROS_Driver git clone -b calibration_devel https://github.com/fmauch/universal_robot.git src/fmauch…

Vue3入门之创建vue3的单页应用(vite+vue)

天行健,君子以自强不息;地势坤,君子以厚德载物。 每个人都有惰性,但不断学习是好好生活的根本,共勉! 文章均为学习整理笔记,分享记录为主,如有错误请指正,共同学习进步。…

电机学-绪论

绪论 电机:根据电磁感应定律和电磁力定律实现机电能量转换和信号传递与转换的电磁机械装置。 电磁感应定律: BiliBili: 法拉第电磁感应定律 BiliBili: 楞次定律 BiliBili: 左手定则、右手定则、右手螺旋定则

GOLLIE : ANNOTATION GUIDELINES IMPROVE ZERO-SHOT INFORMATION-EXTRACTION

文章目录 题目摘要引言方法实验消融 题目 Gollie:注释指南改进零样本信息提取 论文地址:https://arxiv.org/abs/2310.03668 摘要 大型语言模型 (LLM) 与指令调优相结合,在泛化到未见过的任务时取得了重大进展。然而,它们在信息提…

【昇思25天学习打卡营打卡指南-第十八天】基于MobileNetv2的垃圾分类

基于MobileNetv2的垃圾分类 MobileNetv2模型原理介绍 MobileNet网络是由Google团队于2017年提出的专注于移动端、嵌入式或IoT设备的轻量级CNN网络,相比于传统的卷积神经网络,MobileNet网络使用深度可分离卷积(Depthwise Separable Convolut…

玩机社区系统源码 | 2024年最美社区源码 全开源 带后端

简介: 玩机社区系统源码 | 2024年最美社区源码 全开源 带后端 图片: 点击下载

“Pandas数据处理与分析:实用技巧与应用“

目录 # 开篇 1. pandas的series的了解 1.1 pd.Series 创建 1.2 pd.series 的索引使用 1.3 pd.series 之字典/索引 1.4 pandas 转换数据类型 1.5 pandas 通过索引或者通过位置来取值 1.6 pandas 指定行取值 1.7 pands之Series 切片和索引 1.8 pands之Series 的索引和值…

火热夏季:浦语*书生InternLM大模型实战闯关-入门岛之Linux基础知识

一、ssh链接与端口映射并运行hello_wold.py 1.创建开发机 InternStudio创建开发机 2.进入开发机 3.Ssh链接开发机 powerShell终端ssh链接开发机。 4.创建一个hello_world.py文件web demo 5.运行web demo 6.端口映射 7.本地浏览器打开web 二、 VSCODE 远程连接开发机并创建一个…

Mac 上安转文字转 SQL 利器 WrenAI

WrenAI 是一个开源的 Text-SQL 的工具,通过导入数据库结构,通过提问的方式生成 SQL。本文将讲述如何在 MacOS 上安装 WrenAI。要运行WrenAI,首先需要安装 Docker 桌面版。 下载 WrenAI https://github.com/Canner/WrenAI/releases/tag/0.7.…

Spring Boot 高级配置:如何轻松定义和读取自定义配置

目录 1. 环境准备 2. 读取配置数据 2.1 使用 Value注解 2.2 Environment对象 2.3.2.3 自定义对象 这篇博客我们将深入探讨如何在Spring Boot应用中有效地定义和读取自定义配置。掌握这一技巧对于任何希望优化和维护其应用配置的开发者来说都是至关重要的。我们将从基础开始…

HTTPS理解

一个完整的HTTP连接 TCP三次握手接受窗口发送数据关闭连接 接受窗口是用来做什么呢? 它根据自身网络情况设置不同大小的值用来控制对方发送速度,避免对方发送太快,导致网络拥塞。 为什么TCP握手要三次? 1)确认双方的…

镭速Raysync vs MASV:哪个才最合适企业大文件传输

在当前信息爆炸的时代,企业面临的一个关键挑战是如何高效、安全地传输日益增长的大量文件。选择正确的文件传输工具对于企业的日常运作至关重要。本文旨在对比分析两款备受瞩目的企业级大文件传输解决方案——镭速Raysync和MASV,以助企业决策者挑选出最适…

图像中高频信息、低频信息与ComfyUI中图像细节保留的简单研究

🧵背景 在做AI绘图的时候,经常有一些图像的细节需要保留原始图像内容,比如说衣服的细节,商品的文字标签等等,如果这些地方发生了变化,就会导致生成的结果无法直接商用,而让生成的图像完全保留原…

加速你的下载,IDM神器不可错过!快如闪电,稳如老狗

嗨,各位小伙伴!👋👋👋 今天我要安利一个让你的下载体验起飞的神奇工具——Internet Download Manager(简称IDM)🛫。想象一下网速慢得像蜗牛爬的场景,是不是让人抓狂&…

3个方法教你如果快速绕过Excel工作表保护密码

在日常生活中,我们可能会遇到一些特殊情况,比如不小心忘记了Excel文件中设置的打开密码。别担心!这里为您带来一份详细的Excel文件密码移除教程,助您轻松绕过Excel工作表保护。 方法一:使用备份文件 如果您有文件的备…

24暑假计划

暑假计划: 1.从明天起开始将C语言的部分补充完整,这部分的预计在7月24日前完成 2.由于之前的文章内容冗余,接下来进行C语言数据结构的重新编写和后面内容的补充预计8月10号前完成 3.后续开始C的初级学习

【热梗案例】知识点阶段性综合汇总

文章目录 渲染对象、实现统计功能实现删除功能设置发布按钮实现发布按钮的提交功能 直接用CSS的模板&#xff0c;模板代码如下&#xff1a; <template><view class"title">近期热梗</view><view class"out"> <view class&qu…

SuperCLUE最新测评发布,360智脑大模型稳居大模型第一梯队

7月9日&#xff0c;国内权威大模型评测机构SuperCLUE发布《中文大模型基准测评2024上半年报告》&#xff0c;360智脑大模型&#xff08;360gpt2-pro&#xff09;在SuperCLUE基准6月测评中&#xff0c;取得总分72分&#xff0c;超过GPT-3.5-Turbo-0125&#xff0c;位列国内大模型…

马蹄集 oj赛(双周赛7.3-7.14)

目录 围栏木桩 大厨小码哥 最长子段和 旅费 散步 抽奖 海龟 线段树 纸带 异或和 上楼梯 上楼梯2 围栏木桩 难度:黄金时间限制:1秒四占用内存:128 M 某农场有一个由按编号排列的 ,,根木桩构成的首尾不相连的围栏。现要在这个围栏中选取一些太桩&#xff0c;按照原有…