基于Python学习《Head First设计模式》第七章 适配器和外观模式
适配器模式
了解适配器
简单示例
class Duck(ABC):"""鸭子"""@abstractmethoddef quack(self):pass@abstractmethoddef fly(self):passclass MallardDuck(Duck):"""绿头鸭"""def quack(self):print("Quack")def fly(self):print("I'm flying")class Turkey(ABC):"""火鸡"""@abstractmethoddef gobble(self):pass@abstractmethoddef fly(self):pass
class WildTurkey(Turkey):"""野鸡"""def gobble(self):print('Gobble gobble')def fly(self):print("I'm flying a short distance")class TurkeyAdapter(Duck):turkey: Turkeydef __init__(self, turkey: Turkey):self.turkey = turkeydef quack(self):self.turkey.gobble()def fly(self):for _ in range(5):self.turkey.fly()
if __name__ == '__main__':duck = MallardDuck()turkey = WildTurkey()turkey_adapter = TurkeyAdapter(turkey)print('The Turkey says...')turkey.gobble()turkey.fly()print('\nThe Duck says...')duck.quack()duck.fly()print('\nThe TurkeyAdapter says...')turkey_adapter.quack()turkey_adapter.fly()
完整代码
from abc import ABC, abstractmethodclass Duck(ABC):"""鸭子"""@abstractmethoddef quack(self):pass@abstractmethoddef fly(self):passclass MallardDuck(Duck):"""绿头鸭"""def quack(self):print("Quack")def fly(self):print("I'm flying")class Turkey(ABC):"""火鸡"""@abstractmethoddef gobble(self):pass@abstractmethoddef fly(self):passclass WildTurkey(Turkey):"""野鸡"""def gobble(self):print('Gobble gobble')def fly(self):print("I'm flying a short distance")class TurkeyAdapter(Duck):turkey: Turkeydef __init__(self, turkey: Turkey):self.turkey = turkeydef quack(self):self.turkey.gobble()def fly(self):for _ in range(5):self.turkey.fly()class DuckAdapter(Turkey):duck: Duckdef __init__(self, duck: Duck):self.duck = duckself.__reset()def __reset(self):self.rand = (_ for _ in range(4))def gobble(self):self.duck.quack()def fly(self):try:next(self.rand)except StopIteration:self.duck.fly()self.__reset()if __name__ == '__main__':duck = MallardDuck()turkey = WildTurkey()turkey_adapter = TurkeyAdapter(turkey)duck_adapter = DuckAdapter(duck)print('The Turkey says...')turkey.gobble()turkey.fly()print('\nThe Duck says...')duck.quack()duck.fly()print('\nThe TurkeyAdapter says...')turkey_adapter.quack()turkey_adapter.fly()print('\nThe DuckAdapter says...')duck_adapter.gobble()for _ in range(10):duck_adapter.fly()"""运行结果:
The Turkey says...
Gobble gobble
I'm flying a short distanceThe Duck says...
Quack
I'm flyingThe TurkeyAdapter says...
Gobble gobble
I'm flying a short distance
I'm flying a short distance
I'm flying a short distance
I'm flying a short distance
I'm flying a short distanceThe DuckAdapter says...
Quack
I'm flying
I'm flying
"""
适配器模式解析
适配器包装
一个被适配者
适配器定义
类适配器 VS 对象适配器
对象适配器
可以适配一个被适配者类
,类适配器
只能针对特定的
被适配者类
举例: 对象适配器使用组合的方式,可以适配整个Duck类,而类适配器用继承只能支配Duck的具体类,比如绿头鸭类。
但子类类添加新的行为
时,类适配器
更胜一筹。
外观模式
项目:家庭影院
代码实现
class HomeTheaterFacade:"""家庭影院外观"""amp: Amplifiertunner: Tunnerplayer: StreamingPlayerprojector: Projectorlights: TheaterLightsscreen: Screenpopper: PopcornPopperdef __init__(self, amp: Amplifier, tunner: Tunner,player: StreamingPlayer,projector: Projector,lights: TheaterLights,screen: Screen,popper: PopcornPopper):self.amp = ampself.tunner = tunnerself.player = playerself.projector = projectorself.lights = lightsself.screen = screenself.popper = popper
def watch_movie(self,movie:str):print('准备播放电影...')self.popper.on()self.popper.pop()self.lights.lim(10)self.screen.down()self.projector.on()self.projector.wideScrennMode()self.amp.on()self.amp.setStreamingPlayer(self.player)self.amp.setSurroundSound()self.amp.setVolume(5)self.player.on()self.player.play(movie)def end_movie(self):print('停止播放电影')self.popper.off()self.lights.on()self.screen.up()self.projector.off()self.amp.off()self.player.stop()self.player.off()
if __name__ == '__main__':amp = Amplifier()tunner = Tunner()player = StreamingPlayer()projector = Projector()lights = TheaterLights()screen = Screen()popper = PopcornPopper()home_theater = HomeTheaterFacade(amp, tunner, player, projector, lights, screen, popper)home_theater.watch_movie('傲慢与偏见')print()home_theater.end_movie()
完整代码
class Amplifier:"""扩音器"""def on(self):print('打开扩音器')def setStreamingPlayer(self, player):print('设置流媒体输入')def setSurroundSound(self):print('设置环绕音响')def setVolume(self, param):print(f'设置音量为{param}')def off(self):print('关闭扩音器')class Tunner:passclass StreamingPlayer:"""流媒体播放器"""def on(self):print('打开流媒体播放器')def play(self, movie):print(f'播放{movie}')def stop(self):print('停止播放')def off(self):print('关闭流媒体播放器')class Projector:"""投影机"""def on(self):print('打开投影机')def wideScrennMode(self):print('设置投影机为宽屏模式')def off(self):print('关闭投影机')class TheaterLights:"""影院灯光"""def lim(self, param):print('调暗灯光')def on(self):print('打开灯光')class PopcornPopper:"""爆米花机器"""def on(self):print('打开爆米花机器')def pop(self):print('提供爆米花')def off(self):print('关闭爆米花机器')class Screen:"""投影机的屏幕"""def down(self):print('放下屏幕')def up(self):print('收起屏幕')class HomeTheaterFacade:"""家庭影院外观"""amp: Amplifiertunner: Tunnerplayer: StreamingPlayerprojector: Projectorlights: TheaterLightsscreen: Screenpopper: PopcornPopperdef __init__(self, amp: Amplifier, tunner: Tunner,player: StreamingPlayer,projector: Projector,lights: TheaterLights,screen: Screen,popper: PopcornPopper):self.amp = ampself.tunner = tunnerself.player = playerself.projector = projectorself.lights = lightsself.screen = screenself.popper = popperdef watch_movie(self, movie: str):print('准备播放电影...')self.popper.on()self.popper.pop()self.lights.lim(10)self.screen.down()self.projector.on()self.projector.wideScrennMode()self.amp.on()self.amp.setStreamingPlayer(self.player)self.amp.setSurroundSound()self.amp.setVolume(5)self.player.on()self.player.play(movie)def end_movie(self):print('停止播放电影')self.popper.off()self.lights.on()self.screen.up()self.projector.off()self.amp.off()self.player.stop()self.player.off()if __name__ == '__main__':amp = Amplifier()tunner = Tunner()player = StreamingPlayer()projector = Projector()lights = TheaterLights()screen = Screen()popper = PopcornPopper()home_theater = HomeTheaterFacade(amp, tunner, player, projector, lights, screen, popper)home_theater.watch_movie('傲慢与偏见')print()home_theater.end_movie()"""运行结果:
准备播放电影...
打开爆米花机器
提供爆米花
调暗灯光
放下屏幕
打开投影机
设置投影机为宽屏模式
打开扩音器
设置流媒体输入
设置环绕音响
设置音量为5
打开流媒体播放器
播放傲慢与偏见停止播放电影
关闭爆米花机器
打开灯光
收起屏幕
关闭投影机
关闭扩音器
停止播放
关闭流媒体播放器
"""
外观模式定义
适配器模式 VS 外观模式
适配器的意图是:转化
,修改接口
以匹配客户的期望。
外观模式的意图是:简化
,提供子系统的一个简化的接口
。