分类: Java
2010-01-07 20:32:40
abstract class APrototypeRam implements Cloneable {
public Object clone() {
Object o=null;
try {
o=super.clone();//调用父类,即Object的clone()
}
catch(CloneNotSupportedException e) {
System.err.println("APrototypeRam is not cloneable!");
}
return o;
}
}
/** 定义抽象产品Ram的类APrototypeProductCpu
* 同时他也是抽象工厂
*/
abstract class APrototypeCpu implements Cloneable {
public Object clone() {
Object o=null;
try {
o=super.clone();//调用父类,即Object的clone()
}
catch(CloneNotSupportedException e) {
System.err.println("APrototypeCpu is not cloneable!");
}
return o;
}
}
/** 定义具体产品MacRam的类CPrototypeMacRam
* 同时他也是具体工厂
*/
class CPrototypeMacRam extends APrototypeRam{
public String toString() {
return "MacRam";
}
}
/** 定义具体产品WinRam的类CPrototypeWinRam
* 同时他也是具体工厂
*/
class CPrototypeWinRam extends APrototypeRam {
public String toString() {
return "WinRam";
}
}
/** 定义具体产品MacCpu的类CPrototypeMacCpu
* 同时他也是具体工厂
*/
class CPrototypeMacCpu extends APrototypeCpu{
public String toString() {
return "MacCpu";
}
}
/** 定义具体产品WinCpu的类CPrototypeWinCpu
* 同时他也是具体工厂
*/
class CPrototypeWinCpu extends APrototypeCpu{
public String toString() {
return "WinCpu";
}
}
/** 客户端,使用CPrototypeRam和CPrototypeCpu生成如下产品
* MacRam,MacCpu,WinRam,WinCpu
*/
public class Prototype {
public static void main(String[] args) {
/**
* 在生成产品之前,先生成原型产品,以便后面利用它们成批生产相同产品
* 其作用等价于产品工厂
*/
CPrototypeMacRam prototypeMacRam=new CPrototypeMacRam();
CPrototypeWinRam prototypeWinRam=new CPrototypeWinRam();
CPrototypeMacCpu prototypeMacCpu=new CPrototypeMacCpu();
CPrototypeWinCpu prototypeWinCpu=new CPrototypeWinCpu();
CPrototypeMacRam MacRam=(CPrototypeMacRam)prototypeMacRam.clone();
CPrototypeWinRam WinRam=(CPrototypeWinRam)prototypeWinRam.clone();
CPrototypeMacCpu MacCpu=(CPrototypeMacCpu)prototypeMacCpu.clone();
CPrototypeWinCpu WinCpu=(CPrototypeWinCpu)prototypeWinCpu.clone();
System.out.println("打印原形产品与它的克隆产品与比较异同!");
System.out.println("prototypeMacRam:"+prototypeMacRam+" Cloned:"+MacRam);
System.out.println("prototypeWinRam:"+prototypeWinRam+" Cloned:"+WinRam);
System.out.println("prototypeMacCpu:"+prototypeMacCpu+" Cloned:"+MacCpu);
System.out.println("prototypeWinCpu:"+prototypeWinCpu+" Cloned:"+WinCpu);
}
}
通过上面代码,我们可以清楚地看到,用Prototype模式实现工厂模式更为简单,如果再配上原型管理器的话,那么Prototype模式则会变得更为灵活,限于篇幅,本文没有讲到原型管理器,有兴趣的朋友可以参看后文列出的参考文献。但同时,我们也发现,使用原形模式时,有一个不足之处,即在客户端代码里,我们必须显示进行类型转换,这样可能导致错误。为了改正这一点,我想,我们可以使用真正的工厂模式将Prototype模式再封装一遍。对工厂模式的这项功能,恐怕,Prototype原形模式就无能为力了。
总之,工厂模式和原形模式虽然在引入目的上不同,但在实现上,原形模式可以实现工厂模式同样的功能。但读者也不要因为这样,而将两者混为一体,因为,反过来,在将原形模式作为生成本身拷贝的这项功能使用时,工厂模式根本无法取代它。
但实际上,Prototype所模仿的工厂模式的功能,只是“形似而神不似”。我们并不能真正地用原型来代替Factory的功能。
为什么这么说呢?首先让我们来看一看Factory模式引入的本意:Factory引入的目的是将创建类对象的职责从一处转移到另一处。举个例子来说,如果你不希望客户端具有创建某个类对象的能力,那么,你就可以利用工厂模式将创建类对象的职责从客户端转移到服务器端(或者说系统端)。这个例子的最成功的运用就是在Com中,客户只能通过工厂方法创建类的实例,而不充许客户直接创建类的实例。
好了,明白了这一点,让我们再来看看Prototype模式所实现的工厂模式的功能到底是怎么一回事!的确,Prototype模式确实有创建类对象的能力,但是,这种能力,并不符合工厂模式运用的目的,即将创建类对象的职责转移。因为,我们知道,如果要利用Prototype来创建产品,那么,在创建具体的产品之前,我们必须要先生成原型产品。但实际上,原型产品已是符合我们要求的产品,从这种意义上来讲,再通过原型产品来克隆出一个一样的产品根本就没有任何价值。再者,既然原型产品必须暴露给客户,这也违背的工厂模式的原则:即责任分离。
综上所述,如果我们从Prototype模式和Factory模式运用的目的上来看待二者的话,那么这两种模式完全不是同一回事。虽然,Prototype模式看似可以实现Factory模式的创建类对象的功能,但这种相似能力只是“形似而神不似”。
因此,今后我们在运用这两种模式时,一定要分清楚我们的真正目的。这样,才可以更好地选对模式,以方便我们的设计。