浅谈Python设计模式 - 适配器模式
声明:本系列文章主要参考《精通Python设计模式》一书,并且参考一些资料,结合自己的一些看法来总结而来。
从本篇便开始介绍结构型设计模式,而适配器设计模式便是该类设计模式的一种,那么什么是结构型设计模式呢?
结构型设计模式:
其主要用来处理一个系统中不同实体(比如类和对象)之间关系,关注的是提供一种简单的对象组合方式来创造新的功能。
适配器模式
该书中介绍主要为了适配器模式主要用于 帮助我们实现两个不兼容接口之间的兼容。
当我们希望把一个老组件用于一个新组系统或者把一个新组件应用于老系统中,同时在代码无法修改的,或者说无法访问这些代码时(在实际开发中,旧系统的代码修改后牵一而动全身,很容易引起系统的崩溃。)。这时候,我们可以编写一个额外的代码层,该代码层包含让这两个接口之间能够通信需要进行的所有修改。
注:通俗的说就是设计 接口/API,以保证程序符合 开放/封闭 原则,同时保证不修改其他地方接口的调用方式,保持新老代码间的兼容性。
示例:假设有这样一个场景:
一、存在一套旧系统,里面包含 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'
二、下面有需求,需要为该应用丰富更多的功能,而有了接下来的两个类:Synthesizer、Human如下:
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'
从上面代码可以看出: Synthesizer 类,主要动作由play()方法执行。Human类主要动作由speak()方法执行。而原来的类 Computer其动作由execute()方法执行。
并且对于原来的老系统来说,所有动作函数均使用 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)
解析一下:
这里使用一个__init__魔法方法,将新组件的对象添加obj属性中。而其中在__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()))
print('type is {}'.format(type(i)))
注释:其实就是在实例化对象后,使用 Adapter 再将对象包裹一次,最终的调用其实都是调用了 Adapter 类的对象。即:调用适配器对象的execute方法其实就是调用 synth.play或者human.speak方法。
输出结果如下:
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'>
这也是为什么当我们执行下面代码会报错的原因:
for i in objects:
print(i.name)
当然我们可以这样改:
for i in objects:
print(i.obj.name)
这样就可以成功了。这是由于 i对象为适配器对象,只是它的属性字典中,execute 其指向的为 Human.speak 的引用地址。故可以直接使用 i.execute() 进行调用。而其属性字典中没有 Human的name属性,当然我们之前 将 human对象传进来了,而其在适配器对象的obj属性指向的是 human对象,故 i.obj.name 即可调用。
over~~~
浅谈Python设计模式 - 适配器模式的更多相关文章
- 浅谈Python设计模式 -- 责任链模式
声明:本系列文章主要参考<精通Python设计模式>一书,并且参考一些资料,结合自己的一些看法来总结而来. 之前在最开始就聊了Python设计模式有三种,其中关于创建型和结构型设计模式基本 ...
- 浅谈Python设计模式 - 代理模式
声明:本系列文章主要参考<精通Python设计模式>一书,并且参考一些资料,结合自己的一些看法来总结而来. 一.在某些应用中,我们想要在访问某个对象之前执行一个或者多个重要的操作,例如,访 ...
- 浅谈Python设计模式 - 享元模式
声明:本系列文章主要参考<精通Python设计模式>一书,并且参考一些资料,结合自己的一些看法来总结而来. 享元模式: 享元模式是一种用于解决资源和性能压力时会使用到的设计模式,它的核心思 ...
- 浅谈Python设计模式 - 外观模式
声明:本系列文章主要参考<精通Python设计模式>一书,并且参考一些资料,结合自己的一些看法来总结而来. 外观模式 外观模式的核心在于将复杂的内部实现包装起来,只向外界提供简单的调用接口 ...
- 浅谈Python设计模式 - 建造者模式
声明:本系列文章主要参考<精通Python设计模式>一书,并且参考一些资料,结合自己的一些看法来总结而来. 建造者模式 当我们想要创建一个由多个部分构成的对象,而且他们的构建需要一步接一步 ...
- 浅谈Python设计模式 - 抽象工厂模式
声明:本系列文章主要参考<精通Python设计模式>一书,并且参考一些资料,结合自己的一些看法来总结而来. 在上一篇我们对工厂模式中的普通工厂模式有了一定的了解,其实抽象工作就是 表示针对 ...
- 浅谈Python设计模式 - 工厂模式
声明:本系列文章主要参考<精通Python设计模式>一书,并且参考一些资料,结合自己的一些看法来总结而来. 工厂模式: 顾名思义,工厂则是根据提供的不同的材料,生产出不同的产品.那么在编程 ...
- 浅谈Python设计模式 - 原型模式
声明,本系列文章主要参考<精通Python设计模式>一书,并且参考一些资料,结合自己的一些看法来总结而来. 在<精通Python设计模式>中把设计模式分为三种类型: 创建型模式 ...
- 浅谈Python设计模式 - 单例模式
本篇主要介绍一下关于Python的单例模式,即让一个类对象有且只有一个实例化对象. 一.使用__new__方法(基类) 要实现单例模式,即为了让一个类只能实例化一个实例,那么我们可以去想:既然限制创建 ...
随机推荐
- 【DP】【P5615】 [MtOI2019] 时间跳跃
Description 给定 \(n\) 条边,第 \(i\) 条边的长度为 \(i\),每条边都有 \(50\%\) 的概率被选择,求如果选出的边能组成一个平面凸多边形,则方案的权值是方案中边的数量 ...
- nlp语义理解的一点儿看法
nlp领域里,语义理解仍然是难题! 给你一篇文章或者一个句子,人们在理解这些句子时,头脑中会进行上下文的搜索和知识联想.通常情况下,人在理解语义时头脑中会搜寻与之相关的知识.知识图谱的创始人人为,构成 ...
- 第10组 Beta冲刺(4/4)
队名:凹凸曼 组长博客 作业博客 组员实践情况 童景霖 过去两天完成了哪些任务 文字/口头描述 继续学习Android studio和Java 制作剩余界面前端 展示GitHub当日代码/文档签入记录 ...
- Redis常见场景解析
一 前言 Redis是一个key-value存储系统,现在在各种系统中的使用越来越多,大部分情况下是因为其高性能的特性,被当做缓存使用,这里介绍下Redis经常遇到的使用场景. 二 Redis特性 一 ...
- Centos7之搜索命令locate
locate命令[1] 1.#locate命令 所搜索的后台数据库 2.updatedb 更新数据库 3.操作 [root@localhost ~]# ls 222 anaconda-ks.cfg ...
- [经验分享]ThinkPad笔记本无法进入PE环境
首先参考:https://jingyan.baidu.com/article/72ee561a564358e16138df14.html 可以设置Secure Boot然后重启电脑,按F1重新进入BI ...
- 别再说你不会 ElasticSearch 调优了,都给你整理好了
来源:http://tinyurl.com/y4gnzbje 第一部分:调优索引速度 第二部分-调优搜索速度 第三部分:通用的一些建议 英文原文:https://www.elastic.co/guid ...
- ORM之Entity Framework(EF)
ORM之Entity Framework(EF) 一.下载安装: nuget 搜索Entity Framework安装 EntityFramework.Extension是个扩展库根据需要安装 二.使 ...
- 《Linux就该这么学》培训笔记_ch19_使用PXE+Kickstart无人值守安装服务
<Linux就该这么学>培训笔记_ch19_使用PXE+Kickstart无人值守安装服务 文章最后会post上书本的笔记照片. 文章主要内容: 无人值守系统 部署相关服务程序 配置DHC ...
- iOS 测试 WebDriverAgent 简介
WebDriverAgent 是什么 去年的 SeleniumConf 上,Facebook 推出了一款新的iOS移动测试框架 —— WebDriverAgent,当时的推文上,写的还只支持模拟器 ...