Quantcast
Channel: CodeSection,代码区,Python开发技术文章_教程 - CodeSec
Viewing all articles
Browse latest Browse all 9596

通俗 Python 设计模式 : 通俗 Python 设计模式――适配器模式

$
0
0

从这篇开始,介绍书中第二种类型的设计模式――结构型模式。结构型模式 主要用于处理系统中不同实体间的关系 ,如 话题与评论 这类场景。今天介绍其中的 适配器模式 。

适配器模式,通俗的说就是设计 接口/api,以保证程序符合 开放/封闭 原则,保持新老代码间的兼容性。

适配器模式在实际开发中的使用 非常频繁 ,通常在系统的不同层次间,以及为系统添加扩展功能等场景时使用。因为通常情况下,原系统的代码要么无法获取――如库等、要么难以冒险重构――如运行5年以上的老旧系统牵一发而动全身。在设计中使用适配器模式,可以保证在 不修改原系统代码 的前提下,实现 新需求与原系统 的对接。

python 实现适配器模式有多种方式,这里使用书中提供的示例作为介绍。

假设场景:

存在一套旧系统,里面包含 Human 和 Synthesizer 类,如下:

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'

现在新增 Computer 类如下:

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'

并且对于扩展系统来说,所有动作函数均使用 Obj.execute() 来执行。即对于调用者来说,原系统的 Synthesizer.play() 和 Human.speak() 是不存在的,必须像调用 Computer.execute() 一样使用 Synthesizer.execute() 和 Human.execute() 来调用原系统中对象的执行函数。

这就是我们之前提到的场景,无法修改原系统函数,此时新系统就可以采用适配器模式进行设计。

我们可以创建一个 Adapter 类专门用于统一接口,代码如下。

class Adapter: def __init__(self, obj, adapted_methods): self.obj = obj self.__dict__.update(adapted_methods) def __str__(self): return str(self.obj)

简单来说,这里是使用了 Python 的一个特殊语法糖 class.__dict__ 属性,即 类的内部字典 。这个特殊的属性是一个字典,存放了这个类所包含的所以属性,包括方法。所以这里将传入的类进行处理,将需要被适配器处理的方法添加到内部字典中,生成一个属于这个新适配器对象的方法。

接下来,只需要在调用时,对原有系统的类进行封装,即可实现统一使用 execute() 方法执行动作了。代码如下.

def main(): 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()))

简单解释一下,就是在实例化对象后,使用 Adapter 再将对象包裹一次,最终的调用其实都是调用了 Adapter 类的对象。这里我们修改一下 main() 函数,在循环体添加一条打印对象类型的语句:

def new_main(): 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())) print('type is {}'.format(type(i)))

执行结果如下:

the Asus computer executes a program type is <class '__main__.Computer'> the moog synthesizer is playing an electronic song type is <class '__main__.Adapter'> Bob the human says hello type is <class '__main__.Adapter'>

可以看到,扩展系统实现的 Computer 类的对象因为不需要使用适配器处理,所以被识别为 Computer 类,但是经过 Adapter 处理后的 synth 和 human 对象,已经不能被识别为 Synthesizer 和 Human 类,而是被识别为 Adapter 类了。如此一来,就实现了统一接口的目标。

从上面的例子可以看到,适配器模式在需要进行增量式开发的系统中是非常有用的,可以在不修改旧系统的前提下,保证代码的一致性。在合适的场景下有效的提高了代码的健壮性和兼容性。

其实还有一种实现方案,在 这里 可以看到。


Viewing all articles
Browse latest Browse all 9596

Trending Articles