结构型模式---适配器模式

结构型设计模式

结构型设计模式处理一个系统中不同实体(比如,类和对象)之间的关系,关注的是提供一种简单的对象组合方式来创造新功能。

适配器模式

适配器模式是一种结构型设计模式,帮助我们实现两个不兼容接口之间的兼容。首先,解释一下不兼容接口之间的真正含义。如果我们希望把一个老组件用于一个新系统中,或者把一个新组件用于一个老系统中,不对代码进行任何修改就能通信的情况很少见。
但又并非总是能修改代码,或因为我们无法访问这些代码(例如,组件以外部库的方式提供)。在这些情况下,我们可以编写一个额外的代码层,该代码层包含让两个接口之间能够通信需要进行的所有修改。这个代码层就叫适配器。 生活中的例子:如果你有一部智能手机或一台平板电脑,在想把它连接到你的电脑上,就需要使用一个适配器。
应用案例:
在某个产品制造出来之后,需要对新的需求之时,如果希望其仍然有效,则可以使用适配器模式。通常两个不兼容接口中的一个是他方的或是老旧的。
如果一个接口是他方的,那就意味着无法访问源码。如果是老旧的,那么对其重构通常是不切实际的。更进一步,我们可以说修改一个老旧组件的实现
以满足我们的需求,不仅是不切实际的,也违反了开放
/封闭原则。开放/封闭原则是面向对象设计的基本原则之一,声明一个软件实体应该对扩展是开
放的,对修改则是封闭的。本质上这意味着我们应该无需修改一个软件实体的源代码就能扩展其行为。适配器模式遵从开放/封闭原则。
#我们的应用有一个Computer类,用来显示一台计算机的基本信息。我们决定用更多的功能来丰富应用,我们很幸运地在两个与我们应用无关的代码库中发现两个有意思的类,Synthesizer和Human。
#在Synthesizer类中,主要动作由play()方法执行。在Human类中,主要动作由speak()执行。为了表明这两个类是外部的,将其放在一个单独的模块中。
现在有一个问题,客户端仅知道如何调用execute()方法,并不知道play()和speak()。在不改变Synthesizer和Human的前提下,我们该如何做才能让代码有效?
#答案是在test.py中创建一个通用的Adapter类,将一些不同接口的对象适配到统一的接口中。
#Computer类 在test.py文件中
class Computer:
    def __init__(self,name):
        self.name = name

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

    def execute(self):
        return 'executes a program'
#在external.py文件中
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'
#增加适配器后的test.py文件
from external import Synthesizer,Human

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

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

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

#创建适配器类
class Adapter:
    #obj使我们想要适配的对象,adapted_methods是一个字典,
    # 键值对中的键是客户端要调用的方法,值是应该被调用的方法
    def __init__(self,obj,adapted_methods):
        self.obj = obj
        self.__dict__.update(adapted_methods)

    def __str__(self):
        return str(self.obj)

def main():
    #列表objects容纳着所有对象。属于Computer类的可兼容对象不需要适配
    #不兼容的对象则不能直接添加,使用Adapter类来适配它们。
    objects = [Computer('Asus')]
    synth = Synthesizer('moog')
    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()))

if __name__ == '__main__':
    main()

小结

适配器让一件产品在制造出来之后需要应对新的需求时还能工作。在上面的例子中,我们看到如何使用适配器模式,无需修改不兼容模型的源代码就能获得接口的一致性。虽然在Python中我们可以沿袭传统方式使用子类(继承)来实现适配器模式,但是这种技术是一种很棒的替代方案。
posted @ 2019-06-06 09:58  小鲨鱼~  阅读(190)  评论(0编辑  收藏  举报