python设计模式之适配器模式
python设计模式之适配器模式
结构型设计模式一个系统中不同实体(比如,类和对象)之间的关系,关注的是提供一种简单的对象组合方式来创造功能。
适配器模式( Adapter pattern)是一种结构型设计模式,帮助我们实现两个不兼容接口之间的容。首先,解释一下不兼容接口的真正含义。如果我们希望把一个老组件用于一个新系统中,或者把一个新组件用于一个老系统中,不对代码进行任何修改两者就能够通信的情况很少见。但又并非总是能修改代码,或因为我们无法访问这些代码(例如,组件以外部库的方式提供),或因为修改代码本身就不切实际。在这些情况下,我们可以编写一个额外的代码层,该代码层包含让两个接口之间能够通信需要进行的所有修改。这个代码层就叫适配器。
1. 现实生活真的例子
如果你有一部智能手机或者一台平板电脑,在想把它(比如, iPhone手机的闪电接口)连接到你的电脑时,就需要使用一个USB适配器。
2. 软件的例子
Grok是一个Python框架,运行在Zope 3之上,专注于敏捷开发。 Grok框架使用适配器,让已有对象无需变更就能符合指定API的标准 。
Python第三方包Traits也使用了适配器模式,将没有实现某个指定接口(或一组接口)的对象转换成实现了接口的对象 。
3. 应用案例
在某个产品制造出来之后,需要应对新的需求之时,如果希望其仍然有效,则可以使用适配器模式。通常两个不兼容接口中的一个是他方的或者是老旧的。如果一个接口是他方的,就意味着我们无法访问其源代码。如果是老旧的,那么对其重构通常是不切实际的。更进一步,我们可以说修改一个老旧组件的实现以满足我们的需求,不仅是不切实际的,而且也违反了开放/封闭原则。 开放/封闭原则( open/closeprinciple)是面向对象设计的基本原则之一,声明一个软件实体应该对扩展是开放的,对修改则是封闭的。本质上这意味着我们应该无需修改一个软件实体的源代码就能扩展其行为。适配器模式遵从开放/封闭原则 。
因此,在某个产品制造出来之后,需要应对新的需求之时,如果希望其仍然有效,使用适配器是一种更好的方式,原因如下所示。
- [ ] 不要求访问其他地方接口的代码
- [ ] 不违反开放/关闭原则
4. 实现
我们的应用有一个Computer类,用来显示一台计算机的基本信息。这一例子中的所有类,包括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'
在这里, execute方法是计算机可以执行的主要动作。这一方法由客户端代码调用 。
在Synthesizer类中,主要动作由play()方法执行。在Human类中,主要动作由speak()方法执行。为表明这两个类是外部的,将它们放在一个单独的模块中,如下所示。
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'
客户端仅知道如何调用execute()方法,并不知道play()和speak()。在不改变Synthesizer和Human类的前提下,我们该如何做才能让代码有效?适配器是救星!我们创建一个通用的Adapter类,将一些带不同接口的对象适配到一个统一接口中。init()方法的obj参数是我们想要适配的对象, adapted_methods是一个字典,键值对中的键是客户端要调用的方法,值是应该被调用的方法。
class Adapter:
def __init__(self, obj, adapted_methods):
self.obj = obj
self.__dict__.update(adapted_methods)
def __str__(self):
return str(self.obj)
下面看看使用适配器模式的方法。列表objects容纳着所有对象。属于Computer类的可兼容对象不需要适配。可以直接将它们添加到列表中。不兼容的对象则不能直接添加。使用Adapter类来适配它们。结果是,对于所有对象,客户端代码都可以始终调用已知的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()))
现在来看看适配器模式例子的完整代码 。
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 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:
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('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()
输出如下:
the Asus computer executes a program
the moog synthesizer is playing an electronic song
Bob the human says hello
我们设法使得Human和Synthesizer类与客户端所期望的接口兼容,且无需改变它们的源代码。
5. 小结
我们使用适配器模式让两个(或多个)不兼容接口兼容 。无需修改不兼容模型的源代码就能获得接口的一致性。这是通过让一个通用的适配器类完成相关工作而实现的。
python设计模式之适配器模式的更多相关文章
- python 设计模式之适配器模式 Adapter Class/Object Pattern
#写在前面 看完了<妙味>和<华医>,又情不自禁的找小说看,点开了推荐里面随机弹出的<暗恋.橘生淮南>,翻了下里面的评论,有个读者从里面摘了一段自己很喜欢的话出来, ...
- 浅谈Python设计模式 - 适配器模式
声明:本系列文章主要参考<精通Python设计模式>一书,并且参考一些资料,结合自己的一些看法来总结而来. 从本篇便开始介绍结构型设计模式,而适配器设计模式便是该类设计模式的一种,那么什么 ...
- 最全36种python设计模式
设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用.设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案.这些解决方案是众多软件开发人员经过 ...
- 每天一个设计模式-3 适配器模式(Adapteer)
每天一个设计模式-3 适配器模式(Adapteer) 1.现实中的情况 旧式电脑的硬盘是串口的,直接与硬盘连接,新硬盘是并口的,显然新硬盘不能直接连在电脑上,于是就有了转接线.好了,今天的学习主题出来 ...
- Head First 设计模式之适配器模式与外观模式
Head First设计模式之适配器模式与外观模式 前言: 之前讲过装饰者模式,将对象包装起来并赋予新的职责,这一章我们也会将对象进行包装,只不过是让它们看起来不像自己而像是别的东西.这样就可以在设计 ...
- C#设计模式(7)——适配器模式(Adapter Pattern)
一.引言 在实际的开发过程中,由于应用环境的变化(例如使用语言的变化),我们需要的实现在新的环境中没有现存对象可以满足,但是其他环境却存在这样现存的对象.那么如果将“将现存的对象”在新的环境中进行调用 ...
- Java(Android)编程思想笔记02:组合与继承、final、策略设计模式与适配器模式、内部类、序列化控制(注意事项)
1.组合和继承之间的选择 组合和继承都允许在新的类中放置子对象,组合是显式的这样做,而继承则是隐式的做. 组合技术通常用于想在新类中使用现有类的功能而非它的接口这种情形.即在新类中嵌入某个对象,让其实 ...
- 乐在其中设计模式(C#) - 适配器模式(Adapter Pattern)
原文:乐在其中设计模式(C#) - 适配器模式(Adapter Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 适配器模式(Adapter Pattern) 作者:webabc ...
- C#设计模式之七适配器模式(Adapter)【结构型】
一.引言 从今天开始我们开始讲[结构型]设计模式,[结构型]设计模式有如下几种:适配器模式.桥接模式.装饰模式.组合模式.外观模式.享元模式.代理模式.[创建型]的设计模式解决的是对象创建的问题, ...
随机推荐
- 宽度优先搜索--------迷宫的最短路径问题(dfs)
宽度优先搜索运用了队列(queue)在unility头文件中 源代码 #include<iostream>#include<cstdio>#include<queue&g ...
- Java基础(二)流程语句与数组
Java流程语句详解:https://www.cnblogs.com/jiajia-16/p/6008200.html Java数组详解:https://www.cnblogs.com/jiajia- ...
- Linux上搭建文件浏览的web服务(创建软件仓库)(一)
软件仓库的创建方式有很多,这是一种很简单的创建方式: python -m SimpleHTTPServer 快速搭建一个http服务,提供一个文件浏览的web服务. 使用:Python SimpleH ...
- 初识Http
HTTP是一个用在计算机世界里的协议,它确立了一种计算机之间交流通信的规范,以及相关的各种控制 和错误处理方式. HTTP专门用来在两点之间传输数据,不能用于广播.寻址或路由. HTTP传输的是文 ...
- Go语言的跳跃表(SkipList)实现
之所以会有这篇文章,是因为我在学习Go语言跳表代码实现的过程中,产生过一些困惑,但网上的大家都不喜欢写注释- - 我的代码注释一向是写的很全的,所以发出来供后来者学习参考. 本文假设你已经理解了跳表的 ...
- 前端学习(八):CSS
进击のpython ***** 前端学习--CSS 现在的互联网前端分为三层: HTML:超文本标记语言.从语义的角度描述页面结构 CSS:层叠样式表.从审美的角度负责页面样式 JS:Javascri ...
- Django序列化组件Serializers详解
本文主要系统性的讲解django rest framwork 序列化组件的使用,基本看完可以解决工作中序列化90%的问题,写作参考官方文档https://www.django-rest-framewo ...
- pandas之时间数据
1.时间戳Timestamp() 参数可以为各种形式的时间,Timestamp()会将其转换为时间. time1 = pd.Timestamp('2019/7/13') time2 = pd.Time ...
- SpringBoot实现前后端数据交互、json数据交互、Controller接收参数的几种常用方式
1.获取参数的集中常见注解 @PathVariable:一般我们使用URI template样式映射使用,即url/{param}这种形式,也就是一般我们使用的GET,DELETE,PUT方法会使用到 ...
- HTML基础和标签
HTML 1.属性 在开始标签中写的键值对 2.颜色 ①英文 ②16进制代码 例如: #cccccc #ccc (缩写) #000000 ③Rgba(0~255,255,255,0~1) 0~1代 ...