适配器模式(Adapter Pattern)是结构型设计模式之一,主要用于解决接口不兼容问题, 通过将一个类的接口转换成客户端期望的另一个接口,使得原本因接口不匹配而无法协同工作的类能够一起工作。
上面的概念有以下几个关键信息要掌握:
1.接口不兼容
2.转换
3.一起工作
接口不兼容,为啥不重新写一个兼容的接口呢?这个问题其实就道出了设计模式的精髓所在, 工程师琢磨出各种设计模式的目的之一就是尽可能的减少对已经编写好的代码进行修改。 将一个类的接口转换成客户希望的另一个接口,这句话表名,这个类已经有一个接口了,可是并不想直接修改它, 这是重点,一旦修改了,那么单元测试要重新做,之前用这个接口的地方都要重新测试, 甚至可能出现之前的代码发生不兼容的情况,越改就越乱。
那么,能不能写一个新的接口呢,原来的接口,不动了还不行么? 记住,抛开设计模式设计程序永远是可行的,而之所以不这样做, 是因为虽然原来的那个接口没有变化,但这个类有变化呀,多出来一个新的接口。 忘记了目的了么,尽可能少的减少对已经编写好的代码进行修改, 如果这些代码是别人编写的,还有足够的自信修改别的源码么?
既不能修改,也不想新增,怎么办呢,答案是转换,谁来转换,适配器来转换。 适配器把原本不兼容的接口转换成了可以直接使用的接口,从而让两个类可以在一起工作。
理解适配器模式
生活中就有非常贴切的例子可以用来解释什么是适配器,比如手机的充电器,它就是一个很好的适配器。 想要给手机充电,就要给它接入电流,但问题是家用电都是220V 电压,手机能接受的电压是5V的, 如果直接在插座和手机之间扯根线,手机直接就爆了。
插座和手机就是两个不能在一起工作的类,前者输出220V 电压的电,后者只能接收5V电压的电, 这时就需要一个手机充电器来将220V电压的电转换成5V电压的电。
这个例子顺便带出了适配器模式的三个重要概念:
Adaptee
, 被适配的内容,插座就是Adaptee
,它能输出220V 电压的电。Target
, 适配为的内容,目标是一个可以输出5V电压的类。Adapter
, 适配器,把Adeptee
适配成Target
。
适配器解决的是接口不一致的问题,但不能解决功能不一致的问题,既功能原本就是有的, 只是两边对不上,插座可以输出电流,手机也可以充电,但是一个输出的是220V , 一个只能接收5V,这种情况适配器就可以大显身手了。
编码实现
from abc import ABC, abstractmethod
class Power:
def __init__(self):
self.output = 220
def get_output(self):
return self.output
class Transto5V(ABC):
@abstractmethod
def transto5V(self):
pass
class Adapter(Transto5V, Power):
def transto5V(self):
output = super(Adapter, self).get_output()
return output // 44
class Phone:
def charge(self, adapter):
if adapter.transto5V() == 5:
print("手机正在充电")
else:
print("电压过高,无法充电")
if __name__ == "__main__":
adapter = Adapter()
phone = Phone()
phone.charge(adapter)
手机正在充电
Phone
类原本无法与 Power
类一起工作,加入了适配器类 Adapter
, 它是 Power
的子类,
同时也是 Transto5V
类的子类且必须实现 transto5V
方法,
这个方法在 Phone
和 Power
类之间构建起一个联系的桥梁,最终 Power
可以像 Phone
类供电。