github地址:https://github.com/cheesezh/python_design_patterns
适配器模式
适配器模式,将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作[DP]。
当系统的数据和行为都正确,但是接口不符时,我们应该考虑使用适配器模式,目的就是使控制范围之外的一个原有对象与某个接口匹配。适配器模式主要应用于希望复用一些现存的类,但是接口又与复用环境要求不一致的情况。
class Target():"""Target类,这是客户所期待的接口。可以是具体或抽象的类,也可以是接口。"""def request(self):print("普通请求")class Adaptee():"""需要适配的类"""def specific_request(self):print("特殊请求")class Adapter(Target):"""适配器,通过内部包装一个Adaptee对象,把源接口转换成目标接口"""def __init__(self):self.adaptee = Adaptee()def request(self):self.adaptee.specific_request()def main():target = Adapter()target.request()main()
特殊请求
何时使用适配器模式?
想使用一个已经存在的类,但如果它的接口,也就是它的方法和你的要求不想同时,就应该考虑使用适配器模式。
对于公司内部独立开发的系统,类和方法名的规范应当在设计之初就规定好,当接口不相同时,首先不应该考虑使用适配器,而是应该考虑通过重构统一接口。
只有在双方都不太容易修改的时候再使用适配器模式。
但是如果设计之初,我们准备使用第三方开发组件,而这个组件的接口于我们自己的系统接口是不相同的,而我们也完全没有必要为了迎合它而改动自己的接口,此时尽管在开发的设计阶段,也就是可以考虑用适配器模式来解决接口不同的问题。
题目
用程序模拟姚明到国外打NBA初期依赖翻译的场景。
from abc import ABCMeta, abstractmethodclass Player():__metaclass__ = ABCMetadef __init__(self, name):self.name = name@abstractmethoddef attack(self):pass@abstractmethoddef defense(self):passclass Forwards(Player):def attack(self):print("Forward {} attack".format(self.name))def defense(self):print("Forward {} defense".format(self.name))class Guards(Player):def attack(self):print("Guards {} attack".format(self.name))def defense(self):print("Guards {} defense".format(self.name))class ForeignCenter():def __init__(self, name):self.name = namedef jingong(self):print("Center {} jingong".format(self.name))def fangshou(self):print("Center {} fangshou".format(self.name))class Translator(Player):def __init__(self, name):self.foreign_center = ForeignCenter(name)def attack(self):self.foreign_center.jingong()def defense(self):self.foreign_center.fangshou()forwards = Forwards("FFF")
forwards.attack()guards = Guards("GGG")
guards.defense()center = Translator("CCC")
center.attack()
center.defense()
Forward FFF attack
Guards GGG defense
Center CCC jingong
Center CCC fangshou