了解适配器模式???? 客户端通过类的接口访问提供的服务,一般现有类可提供用户的所需功能,而有时不能满足用
了解适配器模式
???? 客户端通过类的接口访问提供的服务,一般现有类可提供用户的所需功能,而有时不能满足用户的期望。例如有两个毫无关联的类组合在一起使用,要么就是修改各自的接口,但是在不修改各自接口的前提下,应该怎么做呢?使用Adapter模式,使得原本需要修改接口的才能在一起工作的两个类可以通过此模式不进行修改接口,在一起工作。
???? 举个例子,面包制作商可以制作面包,蛋糕制作商可以制作蛋糕,某工厂以前请了面包制作商只做面包,而现在还要制作蛋糕。
???? 传统方法?增加一个蛋糕制作的接口,并且在实现中增加制作蛋糕的实现。
public interface MakeFactory{String getCake();String getBread();}
?实现:
public class MakeFactoryImpl implements MakeFactory{public String getBread() {// TODO Auto-generated method stubreturn null;}public String getCake() {// TODO Auto-generated method stubreturn null;}}
?这样就ok了。
但是想想,以前他是做面包的,有做面包的一套体制,如果再把做蛋糕加进去,工序有可能会乱。并且无法工作。
这样我们可以通过Adapter模式。
???
/** * Adaptee 被适配器 * */public class MakeBread {public String getBread(){System.out.println("++++++bread++++");return "bread";};}
?以前我只有一个面包房,现在我还要蛋糕房
public interface MakeFactory{String getCake();String getBread();}
??
?最后看看如何通过适配器模式,将不相连的两个类配在一起工作。
/** * Adapter 适配器 * */public class MakeCake extends MakeBread implements MakeFactory {public String getCake() {System.out.println("++++++cake++++");return "cake";};}
?
这样做,我们的MakeFactory工厂就可以有条不紊的进行制作。
我们测试一下
public class Client {/** * @param args */public static void main(String[] args) {MakeCake m = new MakeCake();m.getCake();m.getBread();}}
?
测试结果
++++++cake++++
++++++bread++++
?
从这里不难看出,此接口可以满足用户的需要。
在上面的UML类图中,Target表成了一个类。实际中,这个要么是一个接口(java中的interface,与李建忠讲义的意图中的接口的概念有点不一样。)。Adaptee就是第三方提供的类。而客户中的代码,不希望直接使用这个第三方类的,于是通过Adapte使用。抛掉Target,就是前面我说的大轮子套小轮子。
适配器从实现的角度上看,是把一个类实例(假如叫objA),注入到另一个类(假定这个类叫类B)中,在这个类B中的方法,使用前面所说的类的实例(即objA)的方法。
从适配器意图上看:它是解决两套接口标准不同的问题。举个例子:
假定有个第三方类叫Man(即人),定义并实现了一个方法叫 feed (吃饭),而这个方法中没有任何参数了。客户不能改变第三方的类的源代码,但是由于实际需要,它想要在这Man的feed方法中加入一个参数---吃饭时间。这时如何办呢?
就是另定义一个类FMan,也定义一个方法,这个方法有一个参数---吃饭时间,在这个类(即FMan)中需要传入Man的实例,在FMan的feed方法里,调用Man实例的feed方法。
在这个适配器中,适配器的实现角度,可以进行总结,推广,再进行新的定义,就会发现这个适配器的内涵,博大精深。如果喜欢佛家之悟的朋友,可把接口、抽象类、适配器模式,联合起来进行观察体会,找出他们的相同点、不同点,会发现这个适配器,真的像机器中的螺丝,它把各个部件有机的组合在一起了。这是一个高度抽象的东东,如果要讲清,需要定义一大套的词语的含义。关于这个适配器模式,就到此为止吧。public class MakeCake extends MakeBread implements MakeFactory { public String getCake() { System.out.println("++++++cake++++"); return "cake"; }; }
这段代码,MakeCake为什么要继承MakeBread呢?难道只是为了获得MakeBread的getBread方法吗?MakeCake和MakeBread应该是并列关系,不应该是继承关系,不应该为了获得某个类的方法,就继承那个类。比如:想使用工具类中的方法,就去继承工具类,这是不对的。 public class MakeCake extends MakeBread implements MakeFactory { public String getCake() { System.out.println("++++++cake++++"); return "cake"; }; }
MakeFactory 接口有两种方法 getBread 和 getCake.
上面代码中MakeCake类实现了MakeFactory 接口。要实现一个接口,则必须全部实现接口的方法。
在MakeCake类中,显示实现了getCake方法。而getBread 方法,是由MakeCake的父类(即MakeBread )中的getBread 方法隐示实现。
也就是说,楼主用了继承与接口实现了适配器。但是正如我前面所说的,这种方式是一种不太好的方式,至少会影响对设计模式的深入理解。同时也违反了设计模式的原则,如果不是特殊情况下,这种方式少用为妙。如果是学设计模式,应掌握通过对象注入的实现方式。
==================================================================
下面是给你的参考建议:
1 认真阅读java面向对象的基本概念。弄清继承、接口、对象的含义。在你的提问中,反映出在这些方面还欠缺一些。
2 对于设计模式,你应掌点掌握适配器模式。但楼主这种方式,你只能了解即可。我前面介绍了适配器模式的另一种方式。姑且叫对象注入吧。
3 强调:对象注入要认真研究揣磨。什么访问者模式、命令模式、职责链模式、组合模式、观察者模式等,从实现角度上看,基本可分成:对象注入+数据结构。事实上"对象注入+数据结构"能弄出千变万化的模式出来。
以上是个人观点,仅供参考。
public class MakeCake extends MakeBread implements MakeFactory { public String getCake() { System.out.println("++++++cake++++"); return "cake"; }; }
MakeFactory 接口有两种方法 getBread 和 getCake.
上面代码中MakeCake类实现了MakeFactory 接口。要实现一个接口,则必须全部实现接口的方法。
在MakeCake类中,显示实现了getCake方法。而getBread 方法,是由MakeCake的父类(即MakeBread )中的getBread 方法隐示实现。
也就是说,楼主用了继承与接口实现了适配器。但是正如我前面所说的,这种方式是一种不太好的方式,至少会影响对设计模式的深入理解。同时也违反了设计模式的原则,如果不是特殊情况下,这种方式少用为妙。如果是学设计模式,应掌握通过对象注入的实现方式。
==================================================================
下面是给你的参考建议:
1 认真阅读java面向对象的基本概念。弄清继承、接口、对象的含义。在你的提问中,反映出在这些方面还欠缺一些。
2 对于设计模式,你应掌点掌握适配器模式。但楼主这种方式,你只能了解即可。我前面介绍了适配器模式的另一种方式。姑且叫对象注入吧。
3 强调:对象注入要认真研究揣磨。什么访问者模式、命令模式、职责链模式、组合模式、观察者模式等,从实现角度上看,基本可分成:对象注入+数据结构。事实上"对象注入+数据结构"能弄出千变万化的模式出来。
以上是个人观点,仅供参考。
那是我按照楼主的意思自己在myeclipse里边写了个。其实makeCake(),在楼主的代码里是getCake,mackeBread是楼主的getBread其实我明白了是运用了类的运行时多态性是吧?谢谢楼上的哥们的建议。做了几个项目后发现基础的那些不经常用的都忘了。呵呵。见笑
22 楼 wuwanli0228 2008-12-16 独孤求学 写道运行机制有点看不明白, 还望解释下
清楚点说。
定义了接口,接口里边有定义个方法供下边实现类实现,(我不太了解适配器模式,不知道为什么作者会写2个方法,我试过写一个方法getCake()就可以。)然后定义了MakeBread定义了getBread方法。再写一个类实MakeFactory接口并继承了MakeBread类。
后边Client实现类里边的
public static void main(String[] args) {
MakeCake m = new MakeCake(); //创建子类对象
m.getCake(); //调用了子类自己的方法
m.getBread(); //子类对象既是父类对象,用到了运行时多态的特性。调用了父类的方法;
}
不太熟悉设计模式只能从入门级别给你说下。。如果不对还望指点; 23 楼 KimHo 2008-12-17 看了后,获益匪浅,谢谢楼主的分享 24 楼 liyun_1981 2009-01-20 wuwanli0228 写道独孤求学 写道运行机制有点看不明白, 还望解释下
清楚点说。
定义了接口,接口里边有定义个方法供下边实现类实现,(我不太了解适配器模式,不知道为什么作者会写2个方法,我试过写一个方法getCake()就可以。)然后定义了MakeBread定义了getBread方法。再写一个类实MakeFactory接口并继承了MakeBread类。
后边Client实现类里边的
public static void main(String[] args) {
MakeCake m = new MakeCake(); //创建子类对象
m.getCake(); //调用了子类自己的方法
m.getBread(); //子类对象既是父类对象,用到了运行时多态的特性。调用了父类的方法;
}
不太熟悉设计模式只能从入门级别给你说下。。如果不对还望指点;
晕死!你对类继承和多态的概念都没搞清楚嘛!子类继承父类,并不是“子类对象既是父类对象”,而是父类中的非private成员变量和方法都给了子类,子类自己可以调用他们。再说一下多态,子类重写继承自父类的方法或者定义父类中申明的abstract方法才是多态的表现! 25 楼 zpoop 2009-04-20 个人觉得,实际上方法重载的复用,也是一种适配方式。 26 楼 uu22 2009-04-22 悟!!!!!! 27 楼 yuanyao 2009-06-04 看了回复,收获不少....