适配器模式和装饰器模式

来源:互联网 发布:淘宝圈子搜索 编辑:程序博客网 时间:2024/05/16 23:01
最近在学习java基础类库的io包,见:http://student.csdn.net/space.php?uid=37718&do=blog&id=1684
在分析类层次结构的过程中,发现了适配器模式和装饰器模式。google后学习并在这里跟大家分享一下。

适配器模式(Adapter)
在学习UML这门课的时候,老师有简单地提到过适配器模式,在我的印象中,适配器模式一直是这样的:
如同硬件驱动的实现,由于各厂商的硬件设备不一样,所以操作系统给出了一个适配器,并由各厂商实现各自的驱动。

但是经过今天的学习之后,我发现适配器模式并不如同我之前理解的那样。
使用适配器是为了使得两个接口不兼容的类能够在不修改各自的接口的前提下顺利地协同工作。举一个经典例子大家就都明白了。

想像这样的一个场景,家里有一个2孔插座,现在你有一部热水壶想烧水,但是热水壶的插头是3叉的,怎么解决呢?这个时候就需要适配器了。 一个简单的适配器就是夹在热水壶插头跟插座之间,一边有3孔插座,另一头是二叉插头的东东。

好了,现在用代码来表达一下这个场景吧,这样会更清晰一些:
class 电器{ 
     在三孔插头下工作(火线,地线,零线){ 
            System.out.println("在三孔插头下工作") ;
      }
}

interface 插座{ 在两孔插头下工作(地线,零线);}

class 适配后的电器 extends 电器 implements 插座{
     在两孔插头下工作(地线,零线){
          火线="";
          在三孔插头下工作(火线,地线,零线)
     }
}

上面是比较伪劣的java代码,大家能明白个中意思就好。
不过这时候大家可能有疑问,就是以上的代码实现,并不是实现了一个独立的转换器(适配器)啊,而等于是在原来的电器类的外面包了一层,使得接口可用。关于这里,我在网上查到的资料是这样说的:

在这里有三个重要的概念,一个是Target 目标,在例中是插座;一个是Adaptee 被适配者,在例中是电器;还有一个是Adapter,在例中是适配后的电器

“单词的直译很容易给没有学过“适配器模式”的同学一些误导,GOF23更多的从他的转换原理类似适配器的工作原理,而事实上并没有转换器这个对象存在,我们还是从它的工作意图并结合类图上来加深理解。”

到底是不是这样,我还要去阅读设计模式原作者的书才好下定论。欢迎大家指正。

本来这个时候已经基本上解决问题,但是事实上,这并不是最好的解决方案。GOF中将上面的方法称做类适配器,即使用继承了实现适配器,另外一种适配器叫做是对象适配器。有一条设计原则是说:“使用组合而不是继承来降低对象之间的耦合”--(看来大牛们都是不支持类继承的啊)

对象适配器的实现也很简单,还是用回上面那个经典例子:
class 电器{ 
     在三孔插头下工作(火线,地线,零线){ 
            System.out.println("在三孔插头下工作") ;
      }
}

interface 插座{ 在两孔插头下工作(地线,零线);}

class 适配后的电器 implements 插座{
     电器 电器A = new 电器();
     在两孔插头下工作(地线,零线){
          火线="";
          电器A.在三孔插头下工作(火线,地线,零线);
     }
}

看,这样以来,适配后的电器类就没有继承电器类,而是直接在类中组合一个电器进来。的而且确,组合和继承是有这样的微妙的联系,即使用他们的任何一种都可以实现一样的重用效果。
(完了,发现越来越能理解那天那篇批判继承的文章了,大牛们的思想果然是高远啊!)

还有一点是有一种简化的适配器实现,即将Adaptee作为参数传入,我个人认为,这应该也是java的io包中的实现方法,就看这个例子就知道了:InputStreamReader(InputStream in) ,没错,io包中字节流对象和字符流对象之间就是应用了适配器模式,InputStream是Adaptee,InputStreamReader是Adapter。 OMG!

“在java 1.1中新引入的面向字符的接口, Reader/Writer, 为了与面向字节的接口匹配使用了适配器模式。”----http://hi.baidu.com/dvdface/blog/item/7bf0232de1152e33349bf78b.html Oh,my dear god!


装饰器模式(Decorator)
刚刚写完IO包的学习总结,有点累哈。不过还是继续把这篇文章弄完。在IO那篇文章里面,我已经提到过了装饰器模式,其实装饰器模式跟适配器模式很像,都是在目标之外包了一层,但是由于动机不同,还是能很容易区分二者的区别的。

装饰器模式强调的是通过组合来动态扩展对象功能。这里的动态我觉得值得深入地思考一下,比如可以通过容器来往被装饰类中添加各种功能。动态添加,这才是装饰器模式的精神实质所在。

本来装饰器就像这样马马虎虎的带过。今晚又看到一篇很好的文章,实在无法不跟大家分享:
http://miaoxiaodong78.blog.163.com/blog/static/18765136200701232434996/#comment=fks_082064084083081074084081082095085094086069081087085069
看完之后,我对装饰器模式已再无遗憾。
0 0
原创粉丝点击