Java学习笔记——设计模式之六.原型模式(浅克隆和深克隆)

 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 }
原文地址:https://www.cnblogs.com/tomasman/p/7030432.html