适配器模式(Adapter Pattern)

定义

适配器模式,将一个接口转换客户希望的另一个接口。适配器将原本不能在一起工作的接口转换成可以在一起工作的接口”
《大话设计模式》
适配器模式一般应用在不能修改源码,在只提供库的情况下又要适配现有代码,则需要增加一层适配器层。个人理解就是在两个不完全比配的接口之间增加一层代码使之匹配。
适配器出现的目的是为了保证不违反面向对象编程的开放封闭原则

UML 示例


@startuml
class  Target
class Client
class Adapter
class Adaptee

Target <|-- Adapter
Target <-- Client
Adaptee <-- Adapter
@enduml

image.png
Adapter实现了Target方法,client最终只是访问target接口类型,Adapter为了使Adaptee可以被client访问,所以做了一层适配,Adapter中存在Adaptee类对象

代码实现

在精通python设计模式中,关于适配器模式的介绍,实现也是相当简单的,只要实现目标接口方法,


# 外部类
class Synthesizer:
    def __init__(self, name):
        self.name = name

    def __str__(self):
        return 'the {} synthesizer'.format(self.name)

    def play(self):
        return 'is playing an electronic song'


class Human:
    def __init__(self, name):
        self.name = name

    def __str__(self):
        return '{} the human'.format(self.name)

    def speak(self):
        return 'says hello'

# 代码
class Adapter(object):
    '''
    这就是适配器类,通过简单的对象解决了这个问题,即将需要适配的目标对象的内容,添加到适配器对象中,
    key:就是目标对象的方法,value:就是需要适配的方法。
    而将需要适配的对象的obj的字典内容(保存了属性信息等)添加到适配器中,这样属性性信息也能够被调用了
    '''
    def __init__(self, obj, adaptermethod):
        self.obj = obj
        self.__dict__.update(adaptermethod)
        self.__dict__.update(obj.__dict__)
        super().__init__()
    
    def __str__(self):
        return str(self.obj)

from external.external import Synthesizer, Human

# Synthesizer 和 Human,都是external外部包的两个类,他们都有各自的paly和speak方法,
# 但client只知道Computer的调用方法即excute,所以在保证原有代码执行excute保持不变,就是适配器需要做的了。
class Computer(object):
    def __init__(self, name):
        self.name = name

    def __str__(self):
        return 'the {} computer'.format(self.name)

    def execute(self):
        return 'executes a program'


def main():
    objects = [Computer('Asus')]
    synth = Synthesizer('moog')
    # 在增加一个适配器类保证Synthesizer也能够被调用
    objects.append(Adapter(synth, dict(execute=synth.play)))
    human = Human('Bob')
    objects.append(Adapter(human, dict(execute=human.speak)))

    for i in objects:
        print('{} {}'.format(str(i), i.execute()))
        print('name: {}'.format(i.name))

if __name__ == "__main__":
    main()

知识点

  1. 重点理解对象的__dict__字典存储的内容,存储对象的属性信息和方法信息,有兴趣可以调试看看
# 输出 i.__dict__的内容
{'execute': <bound method Synthe...0af6c080>>, 'name': 'moog', 'obj': <external.external.S...10af6c080>}
'execute':<bound method Synthesizer.play of <external.external.Synthesizer object at 0x10af6c080>>
'name':'moog'
'obj':<external.external.Synthesizer object at 0x10af6c080>
__len__:3

下集预告 装饰器模式


neilliu
59 声望9 粉丝

coder is coding code snippet,coder change the world!