Python设计模式 - 外观模式
定义
外观模式(Facade Pattern)是一种结构型设计模式,旨在为复杂的子系统提供一个统一的接口,使得客户端可以通过一个简单的接口来访问系统的功能,从而隐藏系统的复杂性。
结构
- 外观类(Facade):提供一个简化的统一接口,供客户端调用。
- 子系统(Subsystem):由多个独立的类或模块组成,提供实际的业务逻辑。
- 客户端(Client):通过调用外观类(Facade)的接口来使用子系统,而不直接与子系统交互。
应用场景
- 简化复杂子系统的接口:当系统由多个复杂子系统组成,而客户端需要使用这些子系统时,外观模式可以提供一个简单、统一的接口来简化客户端的使用。例如,支付系统包含多个子模块(信用卡验证、账单生成、发票打印等),通过外观模式提供一个统一的支付接口,避免客户端直接操作每个子模块。
- 减少子系统之间的依赖性:当你希望减少客户端与多个子系统之间的耦合度时,可以通过外观模式隐藏子系统的实现细节,避免客户端直接与子系统交互。例如,在一个智能家居系统中,客户端不需要关心各个设备的具体实现,而只需通过外观类来控制家庭设备的开关。
优缺点
优点:
- 简化客户端代码:客户端只需要调用外观类的方法,减少了客户端与复杂子系统交互时的代码量和复杂度。
- 降低客户端与子系统之间的耦合度:客户端通过外观类与子系统进行交互,而不直接依赖于子系统的具体实现。这种封装使得客户端不需要关心子系统的内部细节,减少了模块之间的耦合度,提高了系统的可维护性和可扩展性。
缺点:
- 可能造成系统过度封装:有时过度封装可能会导致子系统的某些重要细节被掩盖,外部系统可能无法充分利用子系统的全部功能。
- 增加系统复杂度:引入外观类本身也可能增加系统的复杂度,尤其是当多个外观类用于不同的客户端需求时,可能会使得系统中存在多个“外观类”,增加维护成本和代码冗余。
- 违反开放-关闭原则:在某些场景下,如果需要对子系统的某个功能进行扩展或修改,外观类本身就需要做出修改,违反了开放-关闭原则。
代码示例
class Amplifier:def on(self):print("Amplifier is on.")def off(self):print("Amplifier is off.")class DVDPlayer:def on(self):print("DVD Player is on.")def off(self):print("DVD Player is off.")def play(self, movie):print(f"Playing movie: {movie}")def stop(self):print("Stopped movie.")class Projector:def on(self):print("Projector is on.")def off(self):print("Projector is off.")def wide_screen_mode(self):print("Projector in widescreen mode.")class Screen:def down(self):print("Screen is down.")def up(self):print("Screen is up.")# 外观类:统一协调各个子系统,并负责创建子系统对象
class HomeTheaterFacade:def __init__(self):# 外观类负责创建所有子系统对象self.amplifier = Amplifier()self.dvd_player = DVDPlayer()self.projector = Projector()self.screen = Screen()def watch_movie(self, movie):# 用于准备观看电影,启动所有相关的设备print("\nGet ready to watch a movie...")self.screen.down() # 放下屏幕self.projector.on() # 启动投影仪self.projector.wide_screen_mode() # 设置投影仪为宽屏模式self.amplifier.on() # 启动音响self.dvd_player.on() # 启动DVD播放器self.dvd_player.play(movie) # 播放电影def end_movie(self):# 用于结束观看电影,关闭所有设备print("\nShutting down the movie theater...")self.dvd_player.stop() # 停止播放电影self.amplifier.off() # 关闭音响self.projector.off() # 关闭投影仪self.screen.up() # 收起屏幕# 客户端:通过外观类进行简化操作,不再需要了解具体子系统
if __name__ == "__main__":# 客户端无需创建任何子系统对象,直接使用外观类home_theater = HomeTheaterFacade()# 客户端通过外观类来控制所有设备home_theater.watch_movie("The Matrix") # 开始观看电影home_theater.end_movie() # 结束观看电影
参考
《设计模式的艺术》