设计模式之Facade设计模式

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://xiahunao.cn/news/3225314.html

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

相关文章

XTuner 微调 LLM:1.8B, 部署

扫码立刻参与白嫖A100,书生大模型微调部署学习活动。亲测有效 内容来源:Tutorial/xtuner/personal_assistant_document.md at camp2 InternLM/Tutorial GitHubLLM Tutorial. Contribute to InternLM/Tutorial development by creating an account on G…

Mattermost:一个强大的开源协作平台

Mattermost是一个强大的开源协作平台,基于云原生架构,为企业级用户提供安全、可扩展且自托管的消息传递解决方案。 一、平台特点 开源与定制性:Mattermost是一个开源项目,用户可以根据自身需求定制界面、添加功能或扩展其功能&am…

深入探索大语言模型

深入探索大语言模型 引言 大语言模型(LLM)是现代人工智能领域中最为重要的突破之一。这些模型在自然语言处理(NLP)任务中展示了惊人的能力,从文本生成到问答系统,无所不包。本文将从多个角度全面介绍大语…

文字识别 -- eSearch v1.12.1

软件简介 eSearch是一款功能强大的跨平台软件工具,主要功能包括截屏、OCR文字识别、搜索、翻译、贴图、以图搜图以及录屏等。它不仅支持多屏幕、窗口和控件选择、长截屏等高级截屏功能,还支持离线和在线OCR服务,可进行自定义OCR模型和字典设…

【基于R语言群体遗传学】-15-溯祖理论coalescence

在群体遗传学中,一个非常重要的概念是关注谱系的汇聚(遗传线索的汇合),当我们回溯过去几代人口时。在之前的博客中,我们几乎只处理了随时间推移基因变化的“正向”模拟。 群体遗传学_tRNA做科研的博客-CSDN博客 然而&…

【漏洞复现】时空智友ERP——uploadStudioFile——任意文件上传

声明:本文档或演示材料仅供教育和教学目的使用,任何个人或组织使用本文档中的信息进行非法活动,均与本文档的作者或发布者无关。 文章目录 漏洞描述漏洞复现测试工具 漏洞描述 时空智友ERP是专为医药等行业设计的综合性企业资源规划系统&…

【漏洞复现】锐捷校园网自助服务系统 任意文件读取

声明:本文档或演示材料仅用于教育和教学目的。如果任何个人或组织利用本文档中的信息进行非法活动,将与本文档的作者或发布者无关。 一、漏洞描述 锐捷校园网自助服务系统是用于学校网络管理的一个平台,login_judge.jsf接口存在任意文件读取…

现在国内的ddos攻击趋势怎么样?想了解现在ddos的情况该去哪看?

目前,国内的DDoS攻击趋势显示出以下几个特征: 攻击频次显著增加:根据《快快网络2024年DDoS攻击趋势白皮书》,2023年DDoS攻击活动有显著攀升,总攻击次数达到1246.61万次,比前一年增长了18.1%。 攻击强度和规…

Collection接口及遍历集合的方式Iterator接口、增强for循环的介绍和使用

Collection接口 概述:单列集合的顶级接口格式:其中泛型决定了集合中能存储什么类型的数据,可以统一元素类型,泛型中只能写引用数据类型,如果不写,默认Object类型。等号前面的泛型必须写,等号后…

增强现实(AR)与虚拟现实(VR)的区别?

随着科技的飞速发展,增强现实(AR)与虚拟现实(VR)技术在各个领域展现出巨大的潜力和应用前景。这两种技术虽然在体验和实现方式上有所不同,但都为用户提供了全新的感知体验。本文将详细解析AR和VR的概念、区…

MySQL 面试相关问题

1. MySQL 基础问题1.1 为什么用MySQL?1.2 表属性类型 varchar 和 char 的区别?1.2 什么时候用 varchar 和 char?1.3 Datetime 和 Timestamp 的区别?1.4 一个SQL语句的执行过程,表述下? 2. MySQL 存储引擎相…

凝思安全操作系统安装部署

原文链接:凝思安全操作系统安装部署 Hello,大家好啊!今天给大家带来一篇关于凝思安全操作系统安装部署的文章。凝思安全操作系统是一款注重安全和隐私保护的操作系统,适用于各种高安全性需求的场景。本文将详细介绍如何安装和部署…

万字学习——DCU编程实战

参考资料 2.1 DCU软件栈(DCU ToolKit, DTK) DCU 开发与使用文档 (hpccube.com) DCU软件栈 DCU的软件栈—DCU Toolkit(DTK) HIP(Heterogeneous-Compute Interface for Portability)是AMD公司在2016年提出…

【C++题解】1405 - 小丽找潜在的素数?

问题:1405 - 小丽找潜在的素数? 类型:进制转换 题目描述: 小丽同学在编程中学到了二进制数的概念,她发现,有些二进制数,如果转为 10 进制,就是素数,小丽把这些数称为潜…

机器视觉/自然语言/生成式人工智能综合应用实验平台-实训平台-教学平台

AIGC是人工智能1.0时代进入2.0时代的重要标志,MIT 科技评论也将Al合成数据列为2022年十大突破性技术之一,甚至将生成性Al(Generative Al) 称为是AI领域过去十年最具前景的进展。同时,AIGC领域岗位需求数量暴涨。高校方面在人工智能专业与机器…

【RHCE】转发服务器实验

1.在本地主机上操作 2.在客户端操作设置主机的IP地址为dns 3.测试,客户机是否能ping通

【C++高阶】高效数据存储:理解并模拟实现红黑树Map与Set

📝个人主页🌹:Eternity._ ⏩收录专栏⏪:C “ 登神长阶 ” 🤡往期回顾🤡:了解 红黑树 🌹🌹期待您的关注 🌹🌹 ❀模拟实现Map与Set 📒1.…

【Android】kotlin jdk版本冲突与Kotlin依赖管理插件

1、androidx.activity:activity:1.8.0 依赖版本错误问题 *依赖项“androidx.activity:activity:1.8.0”要求依赖它的库和应用针对版本 34 或更高版本 Android API 进行编译。:app 目前是针对 android-33 编译的。此外…

收银系统源代码-收银端UI风格

智慧新零售收银系统是一套线下线上一体化收银系统,给商户提供含线下收银称重、线上商城、精细化会员管理、ERP进销存、丰富营销活动、移动店务助手等一体化的解决方案。 如Windows版收银(exe安装包)、安卓版收银(apk安装包&#…

LabVIEW平台从离散光子到连续光子的光子计数技术

光子计数技术用于将输入光子数转换为离散脉冲。常见的光子计数器假设光子是离散到达的,记录到来的每一个光子。但是,当两个或多个光子同时到达时,计数器会将其记录为单个脉冲,从而只计数一次。当连续光子到达时,离散光…