That there's some good in this world, Mr. Frodo. And it's worth fighting for.
原型模式(prototype),用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
至于Object.clone()这里就不赘述了。文档看起来可能有些难懂,直接上代码反而更容易理解:
浅克隆:
1 package cn.happy.design_pattern._06prototype.shallowclone; 2 3 public abstract class Prototype { 4 5 private String id; 6 7 String getId() { 8 return id; 9 } 10 11 void setId(String id) { 12 this.id = id; 13 } 14 15 public abstract Prototype mClone(); 16 }
1 package cn.happy.design_pattern._06prototype.shallowclone; 2 3 public class ConcretePrototype extends Prototype implements Cloneable{ 4 5 private Obj obj; 6 public ConcretePrototype() { 7 super(); 8 obj = new Obj(); 9 } 10 11 /* 12 * getter and setter 13 */ 14 Obj getObj() { 15 return obj; 16 } 17 18 19 void setObj(Obj obj) { 20 this.obj = obj; 21 } 22 23 24 @Override 25 public Prototype mClone() { 26 // TODO Auto-generated method stub 27 Prototype prototype = null; 28 try { 29 prototype = (Prototype)this.clone(); 30 } catch (CloneNotSupportedException e) { 31 // TODO Auto-generated catch block 32 e.printStackTrace(); 33 } 34 return prototype; 35 } 36 37 }
1 package cn.happy.design_pattern._06prototype.shallowclone; 2 3 public class Obj { 4 5 private String name; 6 7 String getName() { 8 return name; 9 } 10 11 void setName(String name) { 12 this.name = name; 13 } 14 15 }
1 package cn.happy.design_pattern._06prototype.shallowclone; 2 3 public class Mmain { 4 5 public static void main(String[] args) { 6 ConcretePrototype c1 = new ConcretePrototype(); 7 ConcretePrototype c2 = (ConcretePrototype)c1.mClone(); 8 c1.setId("原型"); 9 c1.getObj().setName("张三"); 10 c2.setId("副本"); 11 c2.getObj().setName("李四"); 12 /* 13 * 浅克隆: 14 * Id是值类型变量,逐位复制,产生新的变量地址;Obj是引用变量,只复制引用,副本和原型共享同一变量地址; 15 * 输出:prototype.shallowclone.ConcretePrototype@15db9742,原型,李四 16 * prototype.shallowclone.ConcretePrototype@6d06d69c,副本,李四 17 */ 18 System.out.println(c1+","+c1.getId()+","+c1.getObj().getName()); 19 System.out.println(c2+","+c2.getId()+","+c2.getObj().getName()); 20 21 } 22 23 }
这里需要提下两种特殊的值类型变量,字符串(其实字符串底层是char数组)和数组。它们虽然是引用类型但是可被浅克隆。大家一试便知。
深克隆:
Prototype 类不变。
1 package cn.happy.design_pattern._06prototype.deepclone; 2 3 public class ConcretePrototype extends Prototype implements Cloneable{ 4 5 private Obj obj; 6 public ConcretePrototype() { 7 super(); 8 obj = new Obj(); 9 } 10 //添加新的构造方法 11 private ConcretePrototype(Obj obj) { 12 super(); 13 this.obj = (Obj) obj.mClone(); 14 } 15 16 17 /* 18 * getter and setter 19 */ 20 Obj getObj() { 21 return obj; 22 } 23 24 25 void setObj(Obj obj) { 26 this.obj = obj; 27 } 28 29 30 @Override 31 public Prototype mClone() { 32 // TODO Auto-generated method stub 33 Prototype prototype = null; 34 //调用新的构造方法 35 prototype = new ConcretePrototype(getObj()); 36 prototype.setId(getId()); 37 return prototype; 38 } 39 40 }
1 package cn.happy.design_pattern._06prototype.deepclone; 2 3 public class Obj implements Cloneable{ 4 //省略属性,这里也许需要更深层克隆。 5 public Object mClone(){ 6 Obj obj = null; 7 try { 8 obj = (Obj)this.clone(); 9 } catch (CloneNotSupportedException e) { 10 // TODO Auto-generated catch block 11 e.printStackTrace(); 12 } 13 return obj; 14 } 15 }
测试类:
1 package cn.happy.design_pattern._06prototype.deepclone; 2 3 public class Mmain { 4 5 public static void main(String[] args) { 6 ConcretePrototype c1 = new ConcretePrototype(); 7 ConcretePrototype c2 = (ConcretePrototype)c1.mClone(); 8 /* 9 * 深克隆:c1与c2中Obj的地址不同了 10 * 输出:...ConcretePrototype@15db9742,null,...Obj@6d06d69c 11 * ...ConcretePrototype@7852e922,null,...Obj@4e25154f 12 */ 13 System.out.println(c1+","+c1.getId()+","+c1.getObj()); 14 System.out.println(c2+","+c2.getId()+","+c2.getObj()); 15 16 } 17 18 }