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

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

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

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Grind 75 | 3. merge two sorted lists
  • 二、分布式软总线是如何高效的传输数据和任务的
  • 案例开发-日程管理-第一期
  • 软件测试基础知识总结与2024最新的软件测试八股文
  • buuctf面具下的flag
  • 甲方安全员应该持有什么心态
  • 【算法】十进制转换为二进制
  • skywalking-1-服务端安装
  • axios get 请求发送 FormData 数据
  • [Vite]vite-plugin-react和vite-plugin-react-swc插件原理了解
  • VBA之Word应用第二章第七节:利用自定义函数修改书签
  • 《昇思25天学习打卡营第01天|qingyun201003》
  • 1.10编程基础之简单排序--02:奇数单增序列
  • 集成测试技术栈
  • 解决Spring Boot应用中的内存优化问题
  • 「译」Node.js Streams 基础
  • 【5+】跨webview多页面 触发事件(二)
  • Java 23种设计模式 之单例模式 7种实现方式
  • JAVA多线程机制解析-volatilesynchronized
  • seaborn 安装成功 + ImportError: DLL load failed: 找不到指定的模块 问题解决
  • SegmentFault 社区上线小程序开发频道,助力小程序开发者生态
  • sessionStorage和localStorage
  • Vue官网教程学习过程中值得记录的一些事情
  • webgl (原生)基础入门指南【一】
  • 阿里云容器服务区块链解决方案全新升级 支持Hyperledger Fabric v1.1
  • 开源SQL-on-Hadoop系统一览
  • 你不可错过的前端面试题(一)
  • 如何优雅地使用 Sublime Text
  • 世界上最简单的无等待算法(getAndIncrement)
  • 数据可视化之 Sankey 桑基图的实现
  • 思考 CSS 架构
  • scrapy中间件源码分析及常用中间件大全
  • ​​​​​​​sokit v1.3抓手机应用socket数据包: Socket是传输控制层协议,WebSocket是应用层协议。
  • #NOIP 2014# day.1 生活大爆炸版 石头剪刀布
  • #Z0458. 树的中心2
  • #我与Java虚拟机的故事#连载06:收获颇多的经典之作
  • #我与Java虚拟机的故事#连载17:我的Java技术水平有了一个本质的提升
  • (C语言)fgets与fputs函数详解
  • (C语言)字符分类函数
  • (带教程)商业版SEO关键词按天计费系统:关键词排名优化、代理服务、手机自适应及搭建教程
  • (附源码)计算机毕业设计高校学生选课系统
  • (六)vue-router+UI组件库
  • (亲测成功)在centos7.5上安装kvm,通过VNC远程连接并创建多台ubuntu虚拟机(ubuntu server版本)...
  • (深入.Net平台的软件系统分层开发).第一章.上机练习.20170424
  • (十)T检验-第一部分
  • (四)Linux Shell编程——输入输出重定向
  • (算法设计与分析)第一章算法概述-习题
  • (一)u-boot-nand.bin的下载
  • (转) 深度模型优化性能 调参
  • *1 计算机基础和操作系统基础及几大协议
  • .NET BackgroundWorker
  • .NET C# 配置 Options
  • .NET 分布式技术比较
  • .NET/C# 异常处理:写一个空的 try 块代码,而把重要代码写到 finally 中(Constrained Execution Regions)
  • .NET编程——利用C#调用海康机器人工业相机SDK实现回调取图与软触发取图【含免费源码】