外观(Facade)模式提供了一个统一的接口,用来访问子系统中的一群接口,外观定义了一个高层接口,让子系统更容易使用。 外观模式很容易理解,它允许我们让客户和子系统之间避免紧耦合。这里先给出它的类图

外观模式改变接口的原因是为了简化接口,之所以取这个名字,是因为它将一个或数个类的复杂的一切都隐藏在背后,只显露出一个干净美好的外观。

下面用一个实例来说明。我们模拟了一个家庭影院,内含DVD播放器、投影机、自动屏幕、环绕立体声,甚至还有爆米花机。我们需要将系统中的每一个组成部分写成一个类。这里以DVD播放器为例,编写一个类

public class DvdPlayer {String description;int currentTrack;Amplifier amplifier;String movie;public DvdPlayer(String description, Amplifier amplifier) {this.description = description;this.amplifier = amplifier;}public void on() {System.out.println(description + " on");}public void off() {System.out.println(description + " off");}public void eject() {movie = null;System.out.println(description + " eject");}public void play(String movie) {this.movie = movie;currentTrack = 0;System.out.println(description + " playing \"" + movie + "\"");}public void play(int track) {if (movie == null) {System.out.println(description + " can't play track " + track + " no dvd inserted");} else {currentTrack = track;System.out.println(description + " playing track " + currentTrack + " of \"" + movie + "\"");}}public void stop() {currentTrack = 0;System.out.println(description + " stopped \"" + movie + "\"");}public void pause() {System.out.println(description + " paused \"" + movie + "\"");}public void setTwoChannelAudio() {System.out.println(description + " set two channel audio");}public void setSurroundAudio() {System.out.println(description + " set surround audio");}public String toString() {return description;}
}

我们在开始观赏电影前需要逐一打开这些组件,这些任务将被写成很多类和方法的调用。在看完电影后,你还要把一切都关掉,如果反向地把这一切动作再进行一次,在代码编写上将非常复杂。 为此我们将采用外观模式,通过实现一个提供更合理的接口的外观类,我们可以将一个复杂的子系统变得容易使用。

public class HomeTheaterFacade {Amplifier amp;Tuner tuner;DvdPlayer dvd;CdPlayer cd;Projector projector;TheaterLights lights;Screen screen;PopcornPopper popper;public HomeTheaterFacade(Amplifier amp, Tuner tuner, DvdPlayer dvd, CdPlayer cd, Projector projector, Screen screen,TheaterLights lights,PopcornPopper popper) {this.amp = amp;this.tuner = tuner;this.dvd = dvd;this.cd = cd;this.projector = projector;this.screen = screen;this.lights = lights;this.popper = popper;}public void watchMovie(String movie) {System.out.println("Get ready to watch a movie...");popper.on();popper.pop();lights.dim(10);screen.down();projector.on();projector.wideScreenMode();amp.on();amp.setDvd(dvd);amp.setSurroundSound();amp.setVolume(5);dvd.on();dvd.play(movie);}public void endMovie() {System.out.println("Shutting movie theater down...");popper.off();lights.on();screen.up();projector.off();amp.off();dvd.stop();dvd.eject();dvd.off();}public void listenToCd(String cdTitle) {System.out.println("Get ready for an audiopile experence...");lights.on();amp.on();amp.setVolume(5);amp.setCd(cd);amp.setStereoSound();cd.on();cd.play(cdTitle);}public void endCd() {System.out.println("Shutting down CD...");amp.off();amp.setCd(cd);cd.eject();cd.off();}public void listenToRadio(double frequency) {System.out.println("Tuning in the airwaves...");tuner.on();tuner.setFrequency(frequency);amp.on();amp.setVolume(5);amp.setTuner(tuner);}public void endRadio() {System.out.println("Shutting down the tuner...");tuner.off();amp.off();}
}

这样一来,我们在测试程序中编写观看电影的代码时,将十分轻松:

public class HomeTheaterTestDrive {public static void main(String[] args) {Amplifier amp = new Amplifier("Top-O-Line Amplifier");Tuner tuner = new Tuner("Top-O-Line AM/FM Tuner", amp);DvdPlayer dvd = new DvdPlayer("Top-O-Line DVD Player", amp);CdPlayer cd = new CdPlayer("Top-O-Line CD Player", amp);Projector projector = new Projector("Top-O-Line Projector", dvd);TheaterLights lights = new TheaterLights("Theater Ceiling Lights");Screen screen = new Screen("Theater Screen");PopcornPopper popper = new PopcornPopper("Popcorn Popper");HomeTheaterFacade homeTheater = new HomeTheaterFacade(amp, tuner, dvd, cd, projector, screen, lights, popper);homeTheater.watchMovie("Raiders of the Lost Ark");//简化的接口homeTheater.endMovie();}
}

设计原则

外观模式体现了又一个设计原则——最少知识原则:只和你的密友谈话。这个原则告诉我们要减少对象之间的交互,只留下几个“密友”,即在设计中,不要让太多的类耦合在一起。

这个原则为我们提供了一些方针:就任何对象而言,在该对象的方法内,我们只应该调用属于以下范围的方法:

  • 该对象本身
  • 被当作方法的参数而传递进来的对象
  • 此方法所创建或实例化的任何对象
  • 此对象的任何组件

值得一提的是,这一原则虽然减少了对象之间的依赖,减少了软件的维护成本;但是采用这个原则也会导致更多的“包装”类被制造出来,以处理和其他组件的沟通,这可能会导致复杂度和开发时间的增加,并降低运行时的性能。在开发过程中,我们需要根据实际情况进行取舍,在本文的例子中,很明显采用最少知识原则带来的软件维护的便利远大于其弊端。

设计模式(8)——外观模式相关推荐

  1. JS常用的设计模式(7)—— 外观模式

    JS常用的设计模式(7)-- 外观模式 外观模式(门面模式),是一种相对简单而又无处不在的模式.外观模式提供一个高层接口,这个接口使得客户端或子系统更加方便调用. 用一段再简单不过的代码来表示 var ...

  2. Swift 中的设计模式 #3 外观模式与适配器模式

    作者:Andrew Jaffee,原文链接,原文日期:2018-09-04 译者:郑一一:校对:BigNerdCoding,pmst,Forelax:定稿:Forelax 本文是我的设计模式系列教程的 ...

  3. Javascript 设计模式之外观模式【讲师辅导】-曾亮-专题视频课程

    Javascript 设计模式之外观模式[讲师辅导]-770人已学习 课程介绍         随着 javascript ES6/7 的发布,很多老版本的设计模式的实现,今天来看是错误的,将被彻底. ...

  4. 移动开发 | Swift 中的设计模式 #3 外观模式与适配器模式

    本文是我的设计模式系列教程的第三篇.在第一篇文章中,我介绍了 创建型模式中的工厂模式和单例模式.在第二篇文章中,又讨论了一下 行为型模式中的观察者模式和备忘录模式. 在本文中,我会就结构型模式中的外观 ...

  5. 如何让孩子爱上设计模式 ——11.外观模式(Facade Pattern)

    如何让孩子爱上设计模式 --11.外观模式(Facade Pattern) 标签: 设计模式初涉 场景引入 相信各位玩过LOL英雄联盟游戏的童鞋,对下面两个英雄都不会陌生吧:       分别是瑞雯和 ...

  6. [设计模式C++]外观模式

    系列文章总结一些比较常见的设计模式,外观模式是由GoF提出的23种设计模式的一种,使用非常简单. 2021-09-16 增加一个例子 区别于代理模式,都像是插入第三者,但是外观模式是统筹管理子系统,就 ...

  7. 研磨设计模式之外观模式(Facade)(解决方案)

    3.2  解决方案 3.2.1  外观模式来解决 用来解决上述问题的一个合理的解决方案就是外观模式.那么什么是外观模式呢? (1)外观模式定义 这里先对两个词进行一下说明,一个是界面,一个是接口. 界 ...

  8. 设计模式之外观模式(Facade)摘录

    23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于如何创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...

  9. java外观设计修改_Java设计模式之外观模式和装饰器模式的设计(精选)

    前言 本篇来学习下结构型模式的外观模式和装饰器模式. 外观模式 简介 外观模式隐藏系统的复杂性,并向客户端提供了一个客户端可以访问系统的接口.这种类型的设计模式属于结构型模式,它向现有的系统添加一个接 ...

  10. 【设计模式】外观模式 ( 概念 | 适用场景 | 优缺点 | 代码示例 )

    文章目录 I . 外观模式概念 II . 外观模式 适用场景 III . 外观模式 优缺点 IV . 外观模式与其它设计模式的联系与区别 V . 外观模式 代码示例 I . 外观模式概念 1 . 外观 ...

最新文章

  1. Linux文件属性和权限
  2. python 如何判断一组数据是否符合正态分布
  3. 三十五、SQL和数据库相关概念
  4. 【kubernetes / k8s 踩坑记录】一定要关闭SWAP
  5. 智能一代云平台(六):移动开发之Ionic研究
  6. C++ 进阶——object slicing 与虚函数与dynamic_cast
  7. Ubuntu用Apache2快速搭建一个HTTP文件服务器
  8. Internet信息服务(IIS)管理器--IIS部署发布网站
  9. 微电网逆变器VF控制_SIMULINK_模型搭建详解_附加“仿真教程”
  10. matlab推导高斯两点求积公式,谁有复何求积公式和高斯求积公式在matlab中实现的... 确定求积公式(如下图)中的待定系数,并指出所构造的......
  11. [转帖]Dockerfile设置默认时区
  12. bp神经网络训练过程matlab,bp神经网络训练时间
  13. 磨金石教育摄影技能干货分享|那些酷炫的照片是怎么拍出来的?
  14. 第二章 Caché JSON 创建和修改动态实体
  15. 缺血性中风和肠道菌群之间的桥梁:短链脂肪酸
  16. 【C语言】交换函数(swap)
  17. 华为 / 小米都看不惯,微信 iOS / 安卓 8.0.30 正式版终于修复转发文件多次保存问题
  18. 2021华为校园招聘算法题
  19. 哗啦啦系统后台新增店铺
  20. matlab 画偏振态,光的偏振态分析MATLAB分析

热门文章

  1. 2.2 Zend_Controller 基础
  2. 2. PHP 自动转义函数
  3. 17、1.7 eclipse使用入门
  4. react給變量賦值并列元素
  5. 2018.11.22 mac中允许所有安装来源的命令 Mac窗口标题显示文件的路径
  6. [poj1325] Machine Schedule (二分图最小点覆盖)
  7. iOS原生的AVFoundation扫描二维码/条形码
  8. 解决清除浮动的最佳办法
  9. 【转】adns解析库——域名解析实例(C++、linux)
  10. AjaxPro.NET实现TextBox智能获取服务端数据功能(Asp.net 2.0)(示例代码下载)