白话设计模式--结构型模式之 适配器模式(Adapter)


适配其实在生活中的例子很多。一个变压器就是最好的例子。
我们不能要求供电局为了我们的随身听而把电压变成12V,只能使用一个变压器把220V的电转换成12V的。这就是个适配器的很好的

例子。新的需求就是我们要12V的电,而原来的电只能提供220V,那么我们就定义一个接口叫做"12V电源使用",然后定一个Adapter

变压器,里面接收(组合)了220V的电源,在里面经过一系列的动作以后,实现了"12V电源使用"这个接口,传出12V电源。

 

设计模式中的适配器模式可以分为对象适配器和类适配器

对象适配器中适配与被适配的对象是组合关系,符合面向对象设计原则:优先选择组合方案,而不是继承方案。

类的适配器中适配与被适配的对象是继承关系,适配器要继承被适配对象和新的接口。由于C#(vb.net)并不支持多继承,所以限制

了类适配器的使用,所以在dotnet中并不推荐使用这种适配方式。

当一个对象A不能满足新需求R时,就可以定义一个适配器Adaper,把A组合到新的Adaper中。在Adaper中使用A的功能和新功能以满

足新需求R。
这句话就说明了适配器模式。适配器就是Adaper,被适配的对象就是A,新需求R可以定义一个接口,并用适配器实现这个接口。

 

在软件设计过程中,也有很多不那么规范的Adapter模式,但是它们也是适配器的思想,也叫做适配器。
如果我们现在存在一个Case类,代表工作。现在有个新的需求,要求对Case根据一些条件进行排序。而Case类本身是没有排序功能的

,这么办呢? Aapter模式就有用了。在这种情况下,我们可以做个Adapter,它实现Icompareable接口。在使用时,直接为Case数

组调用Sort方法,并传入Case数组和刚才新建的adapter对象就可以了。但是这么实现呢?在适配器(CaseAdapter)里实现一个

Compare方法,传进去两个Case对象,根据Case的某个属性,返回一个数值。根据这个值就知道哪个该放在前面了。在这里,并没有

把被适配的对象Case放入Adapter中,而是直接通过参数传入。这并没有符合设计模式的结构,但是却使用了适配器模式的思想.调用代码如下:

 

Code

 

 

那么,如果标准的适配器模式结构是怎么样的呢?
假设我们现在要为Case加上一个TellAlerm的方法,但是却不能去修改Case类,这时就可以使用Adapter了。
我们新建一个CaseAlermAdapterStandard类,然后在构造方法中初始化一个Case对象。然后定义一个方法叫做TellAlarm,返回一个字符串。定义一个ItemCount,返回构造函数中的Case的ItemCount。现在就可以调用了。

调用代码如下:

 

Code

 

 

完整的适配器代码:Adapter design pattern

 

我说完这些,自己却有个疑惑,所谓适配器,是不是就是被适配的对象的所有功能+新功能呢?还是说根据需要选择被适配对象的功能?我个人觉得可能应该是根据需要选择被适配对象的功能.因为有可能我这个适配器不需要那么多功能,只需要被适配对象的一部分功能+新接口定义的功能,就可以满足要求了.

欢迎大家拍砖,我是学习设计模式的新手,希望大家多多指教.

posted on 2008-08-26 15:46 GodSpeed 阅读(1264) 评论(8)  编辑 收藏 网摘

评论

#1楼  2008-08-26 17:03 姜敏      

所谓适配器,是不是就是被适配的对象的所有功能+新功能呢?还是说根据需要选择被适配对象的功能?

说的很晕,你自己都说了变压器的例子,适配器只是一个转换工具,怎么会是所有功能+新功能呢?它起的作用就是把新旧代码统一起来.

例如,一只鸭子它具有分行的动作,每次能飞20,一只火鸡也能飞,但每次只能飞5M,这两种动物看起来很像,如果要统一的话,我们可以让火鸡飞5次,这样外界看火鸡的时候觉感觉不是火鸡,而是鸭子了。这个处理过程就要用到适配器类,它只起到一个转换动物飞行的功能,和什么新旧方法没有关系。   回复  引用  查看    

#2楼 [楼主] 2008-08-26 17:54 GodSpeed      

@姜敏
恩,自己把自己绕进去了.我已经明白了.呵呵,谢谢.   回复  引用  查看    

#3楼  2008-08-26 20:34 懒得起名      

设计模式这种东西 如果不是有过很多次实用 很难真正理解的
建议你参考参考下面几本书 以后写起来质量会高一些:
GoF book(这个你肯定看了 其实不用说了)
大话设计模式
Head First设计模式   回复  引用  查看    

#4楼  2008-08-26 20:36 XMLSpy      

适配器模式和装饰模式差不多   回复  引用  查看    

#5楼  2008-08-26 20:47 懒得起名      

其实适配器也并不是选择一部分功能 而是将对象的各个功能使用方式改变 以使它能像XX一样使用
在Java和C#中 可能会通过迭代器实现某一接口
比如说 将C++风格的迭代器适配到Java风格的迭代器 或者将Java中的Enumerator适配到Iterator 以使它实现Java中的Iterator接口

适配器可能会损失某些功能 但不会实现新功能
用一个现实点的例子 你可以将一个三向插头通过一个适配器适配到二向插孔 这样 地线就没有用了 但你的电器仍然可以勉强工作   回复  引用  查看    

#6楼 [楼主] 2008-08-26 21:04 GodSpeed      

@懒得起名
谢谢推荐~

@XMLSpy
我还没学到装饰模式,不过根据以前的了解,好像真的差不多...哪位知道他们有什么区别吗?



  回复  引用  查看    

#7楼  2008-08-26 21:44 朱良雄      

适配器和装饰模式差别还是比较大的

使用适配器的原因是因为 接口不匹配;而使用装饰模式 是因为功能有欠缺。这两个在概念上还是不一样的。

例如:我们有一个第三方的控件ControlThird,他能够实现我们需要的功能,但是和我们的系统里面的接口不兼容(一般来说是参数的类型的问题),也就是说不能添加到我们的系统所使用的控件体系中去,这个时候就需要给这个控件做一个适配器ControlThirdAdapter,这个适配器的主要工作就像你说的一样 转换电压 ,让我们的系统的其他部分在使用这个第三方控件的时候就好像在使用一个完全Local的控件一样。



而装饰呢,还是用这个ControlThird来说明:他几乎拥有我们所需要的所有功能了,但是 很遗憾他不支持ToolTip这个功能,也就是说,鼠标停留的时候,不能提供一个提示,那怎么办呢?我们用一个功能FuncTips来装饰一下ControlThird.其实是那个FuncTips具有显示Tips的能力,但是看起来好像ControlThird具有一样,我们就说FuncTips装饰了ControlThird..net里面自带的ToolTipControl就是一个很好的装饰者,因为所有的.net控件都是不支持ToolTips的,但是如果让他们和ToolTipControl在同一个Form上,那他们就都被装饰了,都有了这个功能。

  回复  引用  查看    

#8楼 [楼主] 2008-08-27 10:54 GodSpeed      

@朱良雄
那我这么理解可以吗?
装饰者模式就是为原有对象新增加一个功能,新的装饰者对象>=原有对象.
适配器模式就是为一个对象换了一种使用方式.
对吗?

这位大哥说的装饰者模式我听懂了
可是适配器模式却糊涂了,好像适配器也可以做跟装饰者一样的事情?   回复  引用  查看    


标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
Google站内搜索

China-pub 计算机图书网上专卖店!6.5万品种 2-8折!
近千种 9-95 新二手计算图书火热销售中!
开发者征途系统新作:《设计模式——基于C#的工程化实现及扩展》



相关文章:

相关链接:
 
<2008年8月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
31123456

导航

统计

与我联系

搜索

 

常用链接

留言簿

我参加的小组

我参与的团队

我的标签

随笔档案(43)

最新评论

阅读排行榜

评论排行榜