作者 内容
 smilingleo  设计模式之Adaptor---java语言实现(请potian大虾评阅)

原文中的adaptor模式有多继承的概念,而java不支持这个东东,所以我用了一个接口,一个Adaptee类,这样对原文就有了一点修改,
Adaptor成了Adaptee的一个子类,而不是Target的。
是否正确?
下面这个例子应该是一个"对象Adaptor",而不是"类Adaptor",如果是类适配器的话,是否应该将Adaptee类的SpcificRequest()定义成static,但是这个应该是一个已有的应用,用户应该不能修改的呀。是不是java不能实现这个类适配器?请指教!
谢谢。
interface Target{
public void Request();
}
class Adaptee{
public void SpcificRequest(){
System.out.println("This is a Specific Request!");
}
}
class Adapter extends Adaptee implements Target{
public void Request(){
Adaptee ada = new Adaptee();
System.out.println("Now, I can do something specific!");
ada.SpcificRequest();
}
}
public class Client{
public static void main(String args[]){
Target target = new Adapter();
target.Request();
}
}
 01/09/07 08:35 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 wwh0058  回复:臭手的见解,请potian大侠指正

我觉得你的例子可以体现adapter的用处,但是似乎有些问题,原书中说了,可以不用多继承啊,再说你的class adapter有些画蛇添足,
如果继承自Adaptee,则
Adaptee ada = new Adaptee(); ---没有必要;

如果不继承,则在adapter中存在一个adaptee成员实例.
为什么你要混在一起?


由于不能多继承,则:
class Adapter extends Target{
private Adaptee ada ;
public void Request()
{
.....
ada.
}

}


 01/09/07 08:50 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 smilingleo  回复:臭手的见解,请potian大侠指正

嗯!有道理,谢谢。
当时因为就想套用书上的例子,没有想太多。呵呵,谢谢指正!
不过,如果不用
Adaptee ada = new Adaptee();
的话,会抛出一个NullPoint错误。

还有,类适配器呢?兄台有何见解?
 01/09/07 14:04 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 wwh0058  回复:臭手的见解,请potian、smilingleo大侠指正

我觉得类适配器必须用多继承来实现(至少我不知道其他方法)。

再有一点我需要强调,对于对象适配器,
最好象书上那样,将Adaptee作为Adapter构造函数参数(接口指针)传入,不要在Adapter内部创建,否则将丧失动态性(类模式与对象模式的区别)。
这样,当adaptee子类化时Adapter不用变化。

class Adapter extends Target{
public Adapter(adaptee* ada);/*adaptee是接口或纯虚类*/
public void Request(){
System.out.println("Now, I can do something specific!");
ada.SpcificRequest();
}
}
 01/09/07 14:43 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 smilingleo  回复:臭手的见解,请potian、smilingleo大侠指正

嗯,应该是的,如果将adaptee类做为参数的话,可以在其子类化之后,继续使用new Adaptor(Adaptee ada),不错吧。

老兄你是否对c++很熟悉,不过下面代码可能需要更正一点吧,
////////////////
class Adapter extends Target{
Adapter adapter = null;
public Adapter(adaptee ada){
this.adapter = ada;
}
public void Request(){
System.out.println("Now, I can do something specific!");
ada.SpcificRequest();
}
}
/////////////////
 01/09/07 17:33 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 wwh0058  回复:臭手的见解,请potian、smilingleo大侠指正

////////////////
我不大懂,但我觉得有问题,

class Adapter extends Target{
Adapter adapter = null;
public Adapter(adaptee ada){
this.adapter = ada; /*此处会产生浅拷贝问题*/
}
public void Request(){
System.out.println("Now, I can do something specific!");
ada.SpcificRequest();
}
}
/////////////////
我觉得应该是:
class Adapter extends Target{
Adapter* adapter;
public Adapter(adaptee* ada){
this.adapter = ada;
}
public void Request(){
System.out.println("Now, I can do something specific!");
ada->SpcificRequest();
}
}
 01/09/07 17:39 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 smilingleo  回复:臭手的见解,请wwh0058大侠指正

呵呵,这个语言上的问题,我俩不用争了。
我以后的例子还请大虾继续指正!
bow
 01/09/08 09:12 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 potian   回复: 设计模式之Adaptor---java语言实现(请potian大虾评阅)

public void Request(){
Adaptee ada = new Adaptee();
System.out.println("Now, I can do something specific!");
ada.SpcificRequest();
}
不应该在这里实例化adaptee,就像后面你们讨论的,我补充一下。
既然adapter已经从adaptee里继承而来,那么事实上,一旦一个类T继承自另一个类S,Java语言的实现方式就是在子类T的任何一个对象内已经包含了一个超类S的实例,也就是在你的继承层次的任何一条路径中,子类实例总是包含了一个父类实例,这个就是你可以用super存取的东西,甚至大多数情况下你直接在用而不知的东西。
java的缺省构建函数帮你建立了这一过程。如果在子类中定义了一个构建函数,但是超类中没有对应格式的构建函数,譬如:

class S {
}
class T extends S{
public T(String s) {
super(s);
}
}
Java就会无法处理,这是因为Java无法为你建立起对应的超类对象。

这些东西尽管和adapter模式没有直接关系,但是如果知道原因,那么我们也许就会把对象用得更好。

我看你这里的主要问题同时使用了class adapter和Object adapter的混淆,如果是使用object adapter,那么你们后面的讨论是对的.也就是维护了一个对adaptee的指针(如wwh0058所言),以后就可以实现分派。这里我想到的另外一个问题,是Eric好像曾经说过,学习设计模式要看意图,不然的话,所有的设计模式最后看起来都像策略或者Bridge.


你的程序经过修改后示例了adapter的使用,但是有一个问题,如果你需要
让你的适配器能够适配到adaptee子类的时候,你该怎么办?是否直接在adapter的构建函数中直接传入一个adaptee子类实例即可。

这里有两种可能性,一种是你的所有程序和适配只是使用了adpatee接口,adaptee的所有子类都是对adaptee算法或具体实现的不同,这样Object adapter就非常简单了,你创建不同的adaptee之类,把他传入到adapter构建函数中即可。(进一步使用factory method方法将使你的扩展性达到最佳)

但是如果你需要adaptee子类的特定接口,那么你需要建立相应的adapter层次。(可惜我自己没有实际碰到过)。

另一种方法是类adapter,我也没有在实际的应用程序总是用过,只是自己琢磨。因为一般来说,使用adapter总是为了融合已经存在的两个类,那么如果这些类一开始就抽象得不好,譬如方法的重复,或者由于语言不能支持,像Java 只支持对接口的多重实现,你不一定就能用起来,即使用起来。回到我上面的老问题,由于adapter最为adaptee的子类,那么他和adaptee的其他子类就变成了堂兄弟,显然不像用对象方法那么可扩展,可重用。这里也是一个聚集和继承的例子。当然,如果使用GP,还是有可能做到更可重用的。

关于adapter的其他方面的行为,以及继承、聚集和GP,你可以看一看我前几天的一些回复,便于大家讨论。





 01/09/08 23:06 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 smilingleo  回复: 设计模式之Adaptor---java语言实现(请potian大虾评阅)

聆听了两位的指点,我重新设计了这个代码如下,新增加了一个Adaptee的子类,SimpleAdaptee,然后适配这个子类的SpecificRequest()方法。
potian大侠请指教。
这个例子完全是一个object adapter,致于class adapter,我还没有想到用java的实现方法。如果哪位有这样的经验,请不惜赐教。
**************************************************************
class Adaptee{
public void SpecificRequest(){
System.out.println("This is a Specific Request!");
}
}
class SimpleAdaptee extends Adaptee{
public void SpecificRequest(){
System.out.println("This is a new Specific Request by simpleAdaptee!");
}
}
interface Target{
public void Request();
}
class Adapter implements Target{
Adaptee ada = null;
public Adapter(Adaptee adaptee){
this.ada = adaptee;
}
public void Request(){
System.out.println("Now, I can do something specific!");
ada.SpecificRequest();
}
}
public class Client{
public static void main(String args[]){
SimpleAdaptee sada = new SimpleAdaptee();
Target target = new Adapter(sada);
target.Request();
}
}
 01/09/10 09:58 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 wwh0058  回复:还是建议你用指针(或者说引用)

我不知道java的指针如何表示,但在C++中
this.ada = adaptee; 可能会有问题,浅拷贝或者有可能=操作符重载,
所以
class Adapter implements Target{
Adaptee* ada = null;
public Adapter(Adaptee& adaptee){
this.ada = adaptee;
}
 01/09/10 11:47 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 potian  回复:还是建议你用指针(或者说引用)

wwh0058,Java 是没有指针这一概念的,也就是所有的对象都是引用。
到目前为止,Java也不支持操作符重载,Sun可能会在以后加入。
 01/09/10 11:58 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 wwh0058  回复:大侠就是大侠,送你一朵花

 01/09/10 12:03 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 wwh0058  回复:你说的对,我不懂java

 01/09/10 12:06 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 potian  回复:你说的对,我不懂java

这只能说是Java的弱点,C++这方面比Java强。
 01/09/10 12:13 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 fireangel   回复: 设计模式之Adaptor---java语言实现(请potian大虾评阅)

potian,你搞的很清楚,我有些崇拜你了。我会记住这句话“学习设计模式要看意图,不然的话,所有的设计模式最后看起来都像策略或者Bridge. ”
 01/09/10 12:35 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首