前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python设计模式(7):适配器模式

Python设计模式(7):适配器模式

作者头像
不可言诉的深渊
发布2019-07-26 17:46:45
1.9K0
发布2019-07-26 17:46:45
举报
文章被收录于专栏:Python机器学习算法说书人

导言

在软件设计中,为了解决接口不一致的问题,两个软件模块之间往往需要通过一个适配器类 Adapter 进行“适配”。这样的模式叫做适配器设计模式。该模式可以分为两种,分别为类适配器模式(Class Adapter Pattern)和对象适配器模式(Object Adapter Pattern),如图所示。

类适配器模式

这里以问题引入类适配器模式的概念。在图中,假如要使用类 Adaptee 中的方法 Operation1,同时也要使用另外一个方法 Operation2,而 Operation2 没有在类 Adaptee 中,怎样解决该问题呢?

一种解决方案是修改类 Adaptee,在该类中增加代码的实现方法 Operation2。

显然这种方案不可取,因为用户很可能没有该类的源代码,而只有可运行的程序。即使有该类的源代码,修改一个成熟、可靠的类代码,加入新功能的做法只能取得事倍功半的效果。

另一个解决方案是用一个 Target 接口声明所有需要的方法,并且用另外一个 Adapter 类实现 Target 接口中所有的方法。同时,Adapter 类继承 Adaptee 类,如图所示。

将这种结构称为类适配器模式。

类适配器模式的设计要点为,写一个 Target 接口声明所有需要的方法 Operation1 和 Operation2;写一个 Adapter 类继承 Adaptee 类,并且实现接口 Tareget。

适配器模式的各组成部分说明如下。

  1. Target:即所期望的接口。
  2. Adaptee:被继承的类。
  3. Adapter:将 Adaptee 类转化到增加了新功能的 Target 接口。
代码语言:javascript
复制
from abc import ABC, abstractmethod


class Target(ABC):
    @abstractmethod
    def operation1(self):
        pass

    @abstractmethod
    def operation2(self):
        pass


class Adaptee:
    def operation1(self):
        str(self)
        print('adaptee.operation1')


class Adapter(Adaptee, Target):
    def __init__(self):
        self.adaptee = Adaptee()

    def operation2(self):
        print('adaptee.operation2')


if __name__ == '__main__':
    adapter = Adapter()
    adapter.operation1()
    adapter.operation2()

对象适配器模式

假设要使用 Adaptee 类中的方法 Operation1,同时要使用不在该类中的方法 Operation2,前面已采用了类适配器模式的解决方案,这里将介绍另一种解决方案,即遵照类适配器模式相同的思路,但是在 Adapter 类中,采用聚合的办法来实现 Operation1,这种方法即对象适配器模式,其设计图如图所示。

对象适配器模式的设计要点为,在接口 Target 类中声明方法 Operation1 与 Operation2,在 Adapter 类中,需要实现两个方法 Operation1 与 Operation2。在实现 Operation1 时,其代码中实现对 Adaptee 的 Operation1 的调用。

类适配器模式与对象适配器模式在形式上的区别是,类适配器模式对被适配对象采用了继承,而对象适配器对被适配对象采用的则是调用。

代码语言:javascript
复制
from abc import ABC, abstractmethod


class Target(ABC):
    @abstractmethod
    def operation1(self):
        pass

    @abstractmethod
    def operation2(self):
        pass


class Adaptee:
    def operation1(self):
        str(self)
        print('adaptee.operation1')


class Adapter(Target):
    def __init__(self):
        self.adaptee = Adaptee()

    def operation1(self):
        self.adaptee.operation1()

    def operation2(self):
        print('adaptee.operation2')


if __name__ == '__main__':
    adapter = Adapter()
    adapter.operation1()
    adapter.operation2()

关于适配器模式的讨论

何时使用适配器模式

在下列情况下可以使用适配器模式。

  1. 当系统想要使用现有的类,但是现有类的接口不符合系统的需要时。
  2. 当需要通过创建一个可复用的类,使得本来接口不兼容并且无关的类结合在一起工作时。
  3. 在设计中需要改变多个子类接口,在作用相同但名称不同的类或方法之间进行适配时。

适配器模式的作用

适配器模式是将接口不同而功能相近的两个接口加以转换,包括适配器角色补充一些原角色没有但目标接口需要的方法。

但不要以为适配器模式就是为了补充原角色没有的方法而准备的。适配器模式可以用于增加新的方法,但是,其主要意图是转换接口。

适配器模式把一个类的接口转换成客户端所期待的另一种接口,从而使原本因接口不匹配而无法一起工作的两个类能够在一起工作,因此,该模式又称为转换器模式、变压器模式、包装(Wrapper)模式(把已有的一些类包装起来,使之能够有满足需要的接口)等。

适配器模式使得一个系统可以使用那些接口和需求不一致的类,尤其对离架产品代码、工具箱和类库更为适用。适配器模式的重要贡献是强调针对接口编程,客户程序直接针对 Target 接口进行编程。

类适配器模式与对象适配器模式的区别

如果一个被适配源类中有大量的方法,使用类适配器模式比较容易,只需要让 Adapter 类继承被适配的源类即可。而此时使用对象适配器模式则要在 Adapter 类中明确写出 Target 角色中的每个方法,并且在每个方法中要一一调用被适配的源类中的相应方法。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-03-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python机器学习算法说书人 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档