设计模式之适配器模式¶
天可补,海可填,南山可移。日月既往,不可复追。
Author:李东阳
1、什么是适配器模式¶
内容:¶
将一个类的接口转换成客户希望的另一个接口。适配器模式使得那些因为接口不兼容而不能一起工作的那些类可以一起工作。
两种实现方式:¶
-
类适配器: 使用类的多继承
-
对象适配器: 使用组合
角色¶
-
目标接口(Target)
-
待适配的类(Adaptee)
-
适配类(Adapter)
2、继承与组合¶
在介绍适配器模式之前,我先介绍一下继承与组合。我们知道想要实现代码复用,可以用到函数、继承。其实组合也是可以的,那么什么是组合呢?我们都知道,一个类继承了一个类,那么这个新的类就继承了它父类的属性和方法,从而实现了代码复用。而组合就是在这个类的构造函数(初始化)中去实例化一个另一个类的对象,让这个实例化对象成为我们新类的属性。那么同样我们创建的这个类就可以通过这个属性去调用另一个类的属性和方法了,同样实现了代码的复用。
下面来看一看具体代码
# 继承
class A:
def fun(self):
pass
class B(A):
def fun_b(self):
pass
b = B()
b.fun_b()
b.fun()
# 组合
class C:
def __init__(self):
self.a = A()
c = C()
c.a.fun()
3、使用类的多继承实现¶
我们还是拿支付方式举例子,前面讲到“国家规范”(接口)。为了实现支付标准,国家制定了支付规范,即接口。那么现在好了,台湾回归祖国了,他们的支付方式肯定和我们中国大陆的支付方式不同啊。你肯定就说,那就让他们执行我们的规范呗,但是我们要知道人家台湾2000多万人不能说之前的支付方式说换就换嘛,对不对。所以我们就可以到这个适配器了,所谓适配器其实大家都用到过,比如转接口。转接口功能就是,你不改变你的方式,我也不改变我的方式,但是我们之间同样可以交流通信。
那么我们现在就在python中用类的多继承来实现这个功能吧。
现在的情况:
from abc import ABCMeta, abstractmethod
# 国家为了规范支付方法,那么就必须制定一套规范,这个规范在python中就是接口
# 抽象类
# 就是接口
class Pay(mateclass=ABCMeta):
@abstractmethod
def pay(self, money): # 给出支付规范,不去实现,让子类去实现
pass
# 阿里支付
class AliPay(Pay):
def pay(self, money):
print('支付宝支付{}元'.format(money))
# 微信支付
class WechatPay(Pay):
def pay(self, money):
print('微信支付{}元'.format(money))
# 台湾支付
class TaiPay: # 可以看到他们没有实现国家规范(接口)
def cost(self, money): # 他们的支付方式也不一样
print('台湾人民银行支付{}元.'.format(money))
# 如果这时,我们一个内地人通过pay方法在台湾支付
t = TaiPay() # 假设这个t 就是内地人
t.pay() # 他以为在内地,他使用pay方法支付,结果报错
可以发现,内地人在台湾使用pay方法会出错
所以我们要写适配器
from abc import ABCMeta, abstractmethod
# 国家为了规范支付方法,那么就必须制定一套规范,这个规范在python中就是接口
# 抽象类
# 就是接口
class Pay(mateclass=ABCMeta):
@abstractmethod
def pay(self, money): # 给出支付规范,不去实现,让子类去实现
pass
# 阿里支付
class AliPay(Pay):
def pay(self, money):
print('支付宝支付{}元'.format(money))
# 微信支付
class WechatPay(Pay):
def pay(self, money):
print('微信支付{}元'.format(money))
# 台湾支付
class TaiPay: # 可以看到他们没有实现国家规范(接口)
def cost(self, money): # 他们的支付方式也不一样
print('台湾人民银行支付{}元.'.format(money))
# 类适配器
class NewTaiPay(Pay, TaiPay): # 继承Pay接口、TaiPay
def pay(self, money): # 实现pay方法
self.cost(money)
# 如果这时,我们一个内地人通过pay方法在台湾支付
t = TaiPay() # 假设这个t 就是内地人
t.pay(100) # 他以为在内地,他使用pay方法支付,结果报错
# 现在就可以使用pay方法了
nt = NewTaiPay()
nt.pay(100)
4、使用组合实现¶
类的多继承实现的适配器有一个缺点,你有没有发现?
就是一台湾,我们就要写一个适配器,那么以后有更多台湾回归怎么搞?有点麻烦啊。所以,我们就要用到对象适配器
话不多说,直接上代码:
from abc import ABCMeta, abstractmethod
# 国家为了规范支付方法,那么就必须制定一套规范,这个规范在python中就是接口
# 抽象类
# 就是接口
class Pay(mateclass=ABCMeta):
@abstractmethod
def pay(self, money): # 给出支付规范,不去实现,让子类去实现
pass
# 阿里支付
class AliPay(Pay):
def pay(self, money):
print('支付宝支付{}元'.format(money))
# 微信支付
class WechatPay(Pay):
def pay(self, money):
print('微信支付{}元'.format(money))
# 台湾支付
class TaiPay: # 可以看到他们没有实现国家规范(接口)
def cost(self, money): # 他们的支付方式也不一样
print('台湾人民银行支付{}元.'.format(money))
# 类适配器
class NewTaiPay(Pay, TaiPay): # 继承Pay接口、TaiPay
def pay(self, money): # 实现pay方法
self.cost(money)
# 香港支付
class HongKongPay:
def cost(self, money): # 他们的支付方式也不一样
print('香港人民银行支付{}元.'.format(money))
# 对象适配器
class PayAdapter(Pay): # 继承Pay接口
def __init__(self, payment): # 初始化一个传入的支付类对象
self.payment = payment
def pay(self, money): # 实现pay方法
self.payment.cost(money)
# 如果这时,我们一个内地人通过pay方法在台湾支付
t = TaiPay() # 假设这个t 就是内地人
t.pay(100) # 他以为在内地,他使用pay方法支付,结果报错
# 我们把TaiPay这个类传入
p = PayAdapter(TaiPay())
p.pay(100) # 这样我们就能调用pay方法了
p1 = PayAdapter(HongKongPay())
p1.pay(1000) # 同样可以支付