今天看了黑暗浪子的博客,喜欢他的博客,一看就是个爽快人。很高兴,一高兴,就想起来贴篇自己的文章以示高兴。
封装思想的又一种应用。类似挂羊头卖狗肉。比如一个类业已存在(类A),且正合我用,唯一遗憾是该类的方法名与用户要求的不同,那么用另一个新的、方法名符合规定的类套在类A身上是最顺其自然不过的方法了。新类的所作所为无非都是通过调用类A而实现。
在什么场合才需要挂羊头卖狗肉。第一,用户不关心是羊肉还是狗肉,只要是肉就行;第二,你手头没有羊肉而有现成狗肉。第三,用户需要羊头做为通行证。
这是类比,类比形象,但容易误导;所以贴出类比的原型,它是《DesignPatternsExplained》中的一个例子。这个例子是这样的,
有3个类,点、线、正方形。它们都有一个display方法。客户端不关心图形类型,只知道它们是图形,能画出自己来。所以,这里有一个抽象类,叫Shape,它有一个方法叫display. 原来的3个类都来继承Shape. 客户端只知道这个父类 (类比为肉),而不知什么点、线、方块。根据多态,此时Shape类可能是点的实例,也可能是线或正方形的实例,因此它所能画的图形类型也就这三种。如果此时多了一种需求,想让它也能画圆,那么就需要多写一个继承自Shape的Circle类负责画圆。摩拳擦掌准备再展弹指神功之际,突然发现有一个现成的类CircleA(狗肉)可以负起画圆的重任,且此类已经千锤百炼,已应用到好多模块中去了。现成的自然要拿来,问题是让此类直接继承Shape类是不可能的,一来CircleA的接口和Shape类要求继承实现的接口并不匹配,二来,重新修改Circle类会影响到其它已使用该类的模块。所以,在既想使用现成的类,又要匹配Shape的接口的情况下,自然就会创建一个新类,它对外继承了Shape接口(即,客户端要求的羊头,实际是一种契约,一种通行证),对内实际调用Circle类(狗肉,并无贬义)。这个新的类就是适配器。详细的图见下:
http://hiphotos.baidu.com/dapplehou/pic/item/640e7d1eb87dbdc51ad57600.jpg
适配器模式的实现,一般来说有两种方式;一种是用适配器对象包含另一个已经存在的对象,比如图中的Circle 包裹着 XXCircle;另一种方式是通过多继承的方式,比如Circle类可以不去调用XXCircle,而是继承XXCircle,同时再继承Shape(前提是Shape是个接口),既,Circle extends XXCircle implements Shape。它一样可以达到使用现成的类,却仍能匹配用户接口的目的(挂羊头卖狗肉)。
适配器模式也是一种封装,重点强调的接口转置,Façade模式也是一种封装,重点强调的是接口的简化。封装何其常见哉,比如我们写的类也会被别的模块调用,而我们写的类里一定使用了更通用的类,起码会用到基础类库,所以,我们的类一定也不知不觉的进行了封装工作,很可能我们的一个封装里既有对系统接口的简化,又有对部分已有接口的转置,那么这种封装该叫什么模式?所以说,不要拘泥于具体的招数,具体的模式皆是剑招,思想才是剑意。
就Adapter模式而言,你完全可以让这个Adapter除了做转置接口的工作外,再让它实现一些有助于解决实际问题的功能。这就如同练拳时野马分鬃右绷作捋,一开一合,潇洒无限,实战中难道因为我要遵守招式正统,而就不允许分鬃之余顺便吐他口痰么?不要为了模式而模式,约束了自己的创造力。
分享到:
相关推荐
Java适配器的几个小例子,对初学者有帮助
iOS设计模式之适配器模式,简单的demo 去分析对应的设计
1.概念:将两个不兼容的类纠合在一起使用,属于结构型模式,需要有Adaptee(被适配者)和Adaptor(适配器)两个身份. 2.为何使用:我们经常碰到要将两个没有关系的类组合在一起使用,第一解决方案是:修改各自类的接口,...
适配器模式(adaptor) 桥接模式(bridge) 组合模式(composite) 装饰器模式(decorate) 外观模式(facecade) 享元模式(flyweight) 代理模式(proxy) 行为型模式(behaviour) 责任链模式(chainrespon) 命令模式(commond) ...
DBus通讯方式中,设置适配器Adaptor和Interface的通讯方式比较麻烦,重点在于适配器类(Adaptor类)和接口类(Interface类)的生成,Qt有工具可以自动生成相应的类。※建议Qt中DBus通讯使用Interface-Connection方式...
usb 2.0 10 100m ethernet adaptor USB网口转换器驱动
Boost Iterator_adaptor
USB 2.0 10/100M Ethernet Adaptor操作简单, 1.插上USB 2.0 10/100M Ethernet Adaptor设备 2.解压驱动包点击安装 3.刷新或重启电脑。 恭喜你,可以上网了。。。。
ECDSA适配器签名[] 预签名[x] 预先验证[x] 用于预签名的NIZK证明[x] 证人提取[] 签名适应[] Schnorr适配器签名[] 预签名[] 预验证[] 证人提取[] 签名适应[] 实验性 该库实现了加密原语,未经加密社区测试...
USB 2.0 10/100M Ethernet Adaptor有线网卡驱动 很好用
USB 2.0 10/100M Ethernet Adaptor
Switching adaptor 0-30 volts / 3A
形状适配器该存储库包含支持该论文的源代码: ,由和。 Shape Adapter是一个为卷积神经网络(CNN)设计的可学习的池化模块,可自动为训练数据集学习合适的调整大小因子。数据集该项目评估图像分类任务。 对于小...
DBus通讯方式中,设置适配器Adaptor和Interface的通讯方式比较麻烦,重点在于适配器类(Adaptor类)和接口类(Interface类)的生成,Qt有工具可以自动生成相应的类。※建议Qt中DBus通讯使用Interface-Connection方式...
网卡驱动
USB 2.0 10/100M Ethernet Adaptor有线网卡驱动,天蓝透明色和带线的USB网卡都适用卡,支持WIN7 32位。外接网卡,外置USB网卡驱动 平板电脑网卡驱动 以太网驱动亲测可用 USB2.0 Ethernet Adapter是USB2.0接口的...
Android开发框架M-Adaptor,利用JS与Activity交互,减少一定的业务编码量
允许 crudbrella 与猫鼬一起工作##Installation 安装 nodeJS、您选择的数据库和 crudbrella 后,通过 npm 安装此适配器 npm install adaptor-crudbrella-mongoose##Options ###Populate 要使用存储在另一个集合中的...
#HTTP 资源适配器 此 HTTP 资源适配器是的实现,使用作为底层 HTTP 实现。 的测试框架用于针对本地嵌入式 8 实例和上的远程 8 实例执行单元测试。 #Building 和已用于开发。 要在上针对远程 WildFly 或 JBoss 实例...