适配器模式
定义
将一个类的接口变换成客户端期望的另一种接口,从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。
举个例子,读卡器是作为内存卡和笔记本之间的适配器。您将内存卡插入读卡器,再将读卡器插入笔记本,这样笔记本就可以读取内存卡了。
场景
你想使用一个已经存在的类,但它的接口不符合你的需求。
不修改现存的接口,要使该接口适用或兼容新场景业务中,适合使用适配器模式。
适配器可以认为是对现存业务的补偿式应用,所以尽量不要在设计阶段使用适配器模式,在两个系统需要兼容时可以考虑使用适配器模式。
适配器模式与装饰模式
适配器模式和装饰模式有一定的相似性,都起包装的作用,但二者本质上又是不同的,装饰模式的结果,是给一个对象增加了一些额外的职责,而适配器模式,则是将另一个对象进行了“伪装”。
实现
class TargetA(object):
def run(self): # A系统的接口名叫run
print("A系统的接口")
class TargetB(object):
def b_run(self): # B系统的接口名叫b_run
print("B系统的接口")
class Adapter(TargetA):
def __init__(self):
self.adapter = TargetB() # 这个适配器是给B系统做的
def run(self):
self.adapter.b_run() # 适配器的run接口内部调用B系统的b_run接口
if __name__ == "__main__":
a_target = TargetA()
a_target.run()
b_target = Adapter()
b_target.run() # B系统的接口和A系统的接口统一了
通用版适配器
class TargetA:
def run(self):
return "A系统的接口"
class TargetB:
def b_run(self):
return "B系统的接口"
class Adapter:
def __init__(self, obj, adapter_methods):
self.obj = obj
self.__dict__.update(adapter_methods) # 将对象的方法添加到适配器对象的属性字典中,这样就可以通过适配器对象方法进行调用
def __str__(self):
return str(self.obj)
if __name__ == "__main__":
objects = [TargetA()]
b_target = TargetB()
objects.append(Adapter(b_target, dict(run=b_target.b_run)))
for i in objects:
print(i.run())
print('type is {}'.format(type(i)))
优点
1.适配器模式可以让两个接口不同,甚至关系不大的两个类一起运行;
2.提高了类的复用度,经过“伪装”的类,可以充当新的角色;
3.适配器可以灵活“拆卸”。
缺点
过多地使用适配器,会让系统非常零乱。
比如,明明看到调用的是 A 接口,内部却被适配成了 B 接口的实现。
如果一个系统出现很多适配器,无异于一场灾难。如果不是很有必要,建议直接对系统进行重构而不是适配器。