上一篇《python设计模式-适配器模式》介绍了如何将一个类的接口转换成另外一个符合指望的接口。这一篇将要介绍须要一个为了简化接口而改变接口的新模式-外观模式(Facade-Pattern)。python
问题
:若是你组装了一套家庭影院,内含播放器、投影机、自动屏幕、立体声音响、爆米花机等。如何设计一个遥控器,能够简单的操做这个系统中的各个组件呢?
首先来看一下最笨方式观赏电影的步骤:小程序
写成类和方法的调用大概是如下的样子:设计模式
# 打开爆米花机,开始爆米花 poper.on() poper.pop() # 灯光调暗 lights.dim(10) # 放下屏幕 screen.down() # 打开投影仪,设置为宽屏模式 projector.on() projector.setInput(dvd) projector.wideScreenMode() # 打开功放 设置为DVD 调整成环绕立体声模式,音量调到5 amp.on() amp.setDvd(dvd) amp.setSurroundSound() amp.setVolume(5) # 打开dvd 播放器 dvd.on() dvd.play(movie)
能够看到代码中涉及到6个不一样的类,并且电影看完后还须要回退,一切都要再反着重来一遍。怎样简化一下操做呢?
如今,外观模式就能够大展身手了。并发
使用外观模式,能够经过实现一个提供更合理的接口的外观类,将子系统变得更容易使用。固然,原来的接口还在。
先来看一下外观模式如何运做ide
HomeTheaterFacade
,这个类暴露出来几个简单的方法,好比watchMovie
,endMovie
。watchMovie
方法。
注意:
spa
- 能够有多个外观
- 外观提供简化的接口,但不隔离子系统
- 外观将实现从子系统中解耦,好比:如今有个子系统的组件须要升级换代,只须要把外观代码作相应的修改就能够实现
- 外观和适配器均可以包装多个类,可是
外观的意图时简化接口的调用
,而适配器的意图是将接口转换成不一样的接口
。
class HomeTheaterFacade(object): #先声明须要用的子组件 amp = Amplifier() tuner = Tuner() dvd = DvdPlayer() cd = CdPlayer() projector = Projector() lights = TheaterLights() screen = Screen() popper = PopcornPopper() def watchMovie(self, movie): # watchMovie 将以前须要手动处理的任务批量处理 print("Get ready to watch a movie...") # 打开爆米花机,开始爆米花 self.poper.on() self.poper.pop() # 灯光调暗 self.lights.dim(10) # 放下屏幕 self.screen.down() # 打开投影仪,设置为宽屏模式 self.projector.on() self.projector.setInput(dvd) self.projector.wideScreenMode() # 打开功放 设置为DVD 调整成环绕立体声模式,音量调到5 self.amp.on() self.amp.setDvd(dvd) self.amp.setSurroundSound() self.amp.setVolume(5) # 打开dvd 播放器 self.dvd.on() self.dvd.play(movie) def endMovie(self): # endMovie 负责关闭一切,由子系统中的组件完成 print("Shutting movie theater down...") self.popper.off() self.lights.on() self.screen.up() self.projector.off() self.amp.off() self.dvd.stop() self.dvd.eject() self.dvd.off()
def main(): home_theater = HomeTheaterFacade() # 实例化外观 home_theater.watchMovice() # 使用简化方法开启 关闭电影ß home_theater.endMovice()
定义:
外观模式提供了一个统一的接口,用来访问子系统中的一群接口。外观定义了一个高层接口,让子系统更容易使用。
从类图也能够了解到,外观模式的主要意图是提供一个更简单易用的接口。设计
最少知识原则
的意思是减小对象之间的交互,只和几个特定的对象交互。code
这个原则是但愿在设计中,不要耦合太多的类,以避免修改系统时,会影响到其它部分。
好比:若是想从DVD播放器获取音响的音量,能够在Dvd播放器中加入一个方法,用来像音响请求当前音量,而不是先返回音响对象,再从音响对象返回音量。协程
# 很差的实践 def get_volume(): tuner = dvd.tuner() return tuner.get_volume # 好的实践 def get_volume(): # 这里要给dvd 对象加一个get_volume方法 return dvd.get_volume
缺点:
虽然这个原则减小了对象之间的依赖,可是也会致使更多的包装被制造出来(好比上边例子中,就须要给dvd 加一个 get_volume
方法),这也可能会致使系统更复杂。
再回顾一下外观模式的例子,会发现外观模式符合最少知识原则
,客户端只有HomeTheaterFacade
这一个交互对象。它的存在让系统调用变的更简单,而且若是须要子系统有模块须要升级,只须要修改HomeTheaterFacade
这个类就能够完成升级。对象
本文例子来自《Head First 设计模式》。
最后,感谢女友支持和包容,比❤️
也能够在公号输入如下关键字获取历史文章:公号&小程序
| 设计模式
| 并发&协程