原型模式(prototype)为创建型对象模式,它是用原型实例来指定创建对象的类型的,并通过拷贝这些原型来创建新的对象。也就是说,这次我们创建新的对象和以前创建对象的方法有些不同,以前创建新的对象是用new方法作用于类上来实现的,现在我们不这样做了,给定一个类的实例,我们通过克隆这个类的实例来创建新的实例,显然,这个类本身要有能够实现“克隆”机制的方法才行,这样用该类创建出的对象才能拥有“克隆”自己的能力。通过查看java API文档可知,Java语言本身具有克隆对象的能力,因为Java.lang.Object对象中有一个clone()方法,但是想用这个方法还要做一些事情,那就是要实现Cloneable接口,这里给个小例子:
1 public class Test{ 2 3 public static void main(String[] args){ 4 Clon clon=new Clon(); 5 clon.setStr("helloworld"); 6 Clon clon2=(Clon)clon.clone(); 7 System.out.println("clon.getClass()==clon2.getClass() ? "+(clon.getClass()==clon2.getClass())); 8 System.out.println("clon==clon2 ? "+(clon==clon2)); 9 System.out.println("clon.getSub()==clon2.getSub() ? "+(clon.getSub()==clon2.getSub())); 10 } 11 } 12 13 class Clon implements Cloneable{ 14 private String str=null; 15 private substance sub=new substance(); 16 public void setStr(String str){ 17 this.str=str; 18 } 19 public substance getSub(){ 20 return sub; 21 } 22 public void printStr(){ 23 System.out.println(str); 24 } 25 public Object clone(){ 26 Clon to_clon=null; 27 try{ 28 to_clon=(Clon)super.clone(); 29 }catch(CloneNotSupportedException e){ 30 System.out.println(e); 31 }finally{ 32 return to_clon; 33 } 34 } 35 } 36 class substance{ 37 38 }
运行结果如下:
clon.getClass()==clon2.getClass() ? true
clon==clon2 ? false
clon.getSub()==clon2.getSub() ? true
调用clone方法实现的复制是“浅拷贝”(浅克隆),也就是说克隆的不够彻底,被克隆出的对象中的变量和原来的对象中的变量有相同的值,但是克隆出的对象中的引用和原对象中的引用的指向是相同的,所以运行结果的最后一行clon.getSub()==clon2.getSub()为真,它们返回的引用的指向是同一个对象。这就是“浅克隆”,至于“深克隆”机制,请看java编程之java浅拷贝和深拷贝,在该节,我总结了一点东西。
现在我们知道了,原型模式就是利用克隆的方式去创建新的对象,那么,这种模式与其他创建型模式有什么不同呢?
我们知道,工厂模式中,工厂类和产品类具有一定的对应关系,工厂类的等级结构要随产品类的等级结构变化而变化;但当采用原型模式时就不会有这种变化,当进行产品扩展时,我们只需要新产品的原型实例就可以通过拷贝方式创建新的产品对象(虽然对象中的属性值是和原型相同的,但是拿到这个新的产品对象后,你可以利用对象的内部方法任意修改自己想要的属性值,例如运用setXXX()方法等)。从这点来说,原型模式比其他创建型模式更为灵活。例如上面的例子中,你只需执行Clon clon3=(Clon)clon.clone()就又创建一个新的对象,注意这里,我们并未用new关键字去创建对象,所有创建型模式的终极目标都是对new关键字应该放在什么地方进行探索和封装,以便设计出更具合理性的对象创建方法,以上是对原型模式的学习总结,不足之处,恳请批评指正。