楼子湾

导航

 

一.原型(ProtoType)模式定义: 

给出一个原型对象实例来指定创建对象的类型,并通过拷贝这些原型的方式来创建新的对象。

原型模式的简单程度仅次于单例模式的简单模式,它的定义可以理解为对象的拷贝,通过拷贝一个已有对象创建新对象,这就是原型模式。

设计类图:

 

 

 

 

二.场景

需要大量创造重复场景且构造函数复杂时,比如需要先读取数据或者加载文件

三.原型模式又称为克隆模式:有两种

浅克隆:实现cloneable接口

深度克隆:方式一.实现cloneable接口;方式二.序列化和反序列化

四.浅克隆与深度克隆----通过cloneable实现

java实现克隆必须实现cloneable接口,该接口是个空接口

浅克隆:类本身实现cloneable接口,引用类或者内部类未实现cloneable接口

 1 package com.design.clone;
 2 
 3 public class TestClone implements Cloneable {
 4     private String testCloneName="hello";
 5     private int testCloneInt = 1;
 6     private TestObj testObj = new TestObj();
 7     @Override
 8     protected TestClone clone() throws CloneNotSupportedException {
 9         return (TestClone) super.clone();
10     }
11 
12     public String getTestCloneName() {
13         return testCloneName;
14     }
15 
16     public void setTestCloneName(String testCloneName) {
17         this.testCloneName = testCloneName;
18     }
19 
20     public int getTestCloneInt() {
21         return testCloneInt;
22     }
23 
24     public void setTestCloneInt(int testCloneInt) {
25         this.testCloneInt = testCloneInt;
26     }
27 
28     public TestObj getTestObj() {
29         return testObj;
30     }
31 
32     public void setTestObj(TestObj testObj) {
33         this.testObj = testObj;
34     }
35 
36     @Override
37     public String toString() {
38         final StringBuilder sb = new StringBuilder("TestClone{");
39         sb.append("testCloneHashCode='").append(this.hashCode()).append('\'');
40         sb.append(",testCloneName='").append(testCloneName).append('\'');
41         sb.append(", testCloneInt=").append(testCloneInt);
42         sb.append(", testObjHashCode=").append(testObj.hashCode());
43         sb.append(", testObjInt=").append(testObj.getTestObjInt());
44         sb.append('}');
45         return sb.toString();
46     }
47 }
48 
49 
50 //引用代码未实现clone接口
51 package com.design.clone;
52 
53 public class TestObj {
54     private int testObjInt=1;
55 
56     public int getTestObjInt() {
57         return testObjInt;
58     }
59 
60     public void setTestObjInt(int testObjInt) {
61         this.testObjInt = testObjInt;
62     }
63 }
64 
65 测试:
66  public static void main(String[] args) throws CloneNotSupportedException {
67         TestClone testClone = new TestClone();
68         System.out.println("克隆前:" + testClone.toString());
69         TestClone cloneObj = testClone.clone();
70         System.out.println("克隆的新对象:" + cloneObj.toString());
71         System.out.println("================修改克隆对象的值,看是否会修改原对象属性值==============");
72         cloneObj.setTestCloneName("world");
73         cloneObj.setTestCloneInt(-2);
74         cloneObj.getTestObj().setTestObjInt(0);
75         System.out.println("被克隆对象testCone=" + testClone.toString());
76         System.out.println("克隆对象:" + cloneObj.toString());
77     }

 

结果:

 

 

从打印结果可以看出来原对象testClone 的hashCode和克隆出来的对象的hashcode不一样,也就是说clone并不是把原对象地址引用复制给新对象,而是重新再内存中开辟了一块新空间,将testClone复制过去,将新地址给新对象

但是testObj的hashCode却是相同的,也就是两个指向了同一个对象,当其中一个对象改变引用的属性时,另外一个也会跟着改变,上面打印的改变的克隆的testObj的属性,原对象的也跟着改变了,

testClone对象的基本数据类型属性在clone的时候开辟了新内存,所以互不影响

 

深度克隆:引用对象也实现cloneable接口, 同时TestClone的clone方法需要对TestObj进行克隆赋值操作

 1 package com.design.clone;
 2 
 3 public class TestObj implements Cloneable{
 4     private int testObjInt=1;
 5 
 6     public int getTestObjInt() {
 7         return testObjInt;
 8     }
 9 
10     public void setTestObjInt(int testObjInt) {
11         this.testObjInt = testObjInt;
12     }
13 
14     @Override
15     protected TestObj clone() throws CloneNotSupportedException {
16         return (TestObj) super.clone();
17     }
18 }
19 
20 package com.design.clone;
21 
22 public class TestClone implements Cloneable {
23     private String testCloneName="hello";
24     private int testCloneInt = 1;
25     private TestObj testObj = new TestObj();
26     @Override
27     protected TestClone clone() throws CloneNotSupportedException {
28         TestClone clone = (TestClone) super.clone();
29         clone.setTestObj(clone.getTestObj().clone());
30         return clone;
31     }
32 
33     public String getTestCloneName() {
34         return testCloneName;
35     }
36 
37     public void setTestCloneName(String testCloneName) {
38         this.testCloneName = testCloneName;
39     }
40 
41     public int getTestCloneInt() {
42         return testCloneInt;
43     }
44 
45     public void setTestCloneInt(int testCloneInt) {
46         this.testCloneInt = testCloneInt;
47     }
48 
49     public TestObj getTestObj() {
50         return testObj;
51     }
52 
53     public void setTestObj(TestObj testObj) {
54         this.testObj = testObj;
55     }
56 
57     @Override
58     public String toString() {
59         final StringBuilder sb = new StringBuilder("TestClone{");
60         sb.append("testCloneHashCode='").append(this.hashCode()).append('\'');
61         sb.append(",testCloneName='").append(testCloneName).append('\'');
62         sb.append(", testCloneInt=").append(testCloneInt);
63         sb.append(", testObjHashCode=").append(testObj.hashCode());
64         sb.append(", testObjInt=").append(testObj.getTestObjInt());
65         sb.append('}');
66         return sb.toString();
67     }
68 }
69 
70 package com.design.clone;
71 
72 public class Client {
73     public static void main(String[] args) throws CloneNotSupportedException {
74         TestClone testClone = new TestClone();
75         System.out.println("克隆前:" + testClone.toString());
76         TestClone cloneObj = testClone.clone();
77         System.out.println("克隆的新对象:" + cloneObj.toString());
78         System.out.println("================修改克隆对象的值,看是否会修改原对象属性值==============");
79         cloneObj.setTestCloneName("world");
80         cloneObj.setTestCloneInt(-2);
81         cloneObj.getTestObj().setTestObjInt(0);
82         System.out.println("被克隆对象testCone=" + testClone.toString());
83         System.out.println("克隆对象:" + cloneObj.toString());
84     }
85 }

 

测试结果:

 

 从上面打印结果看出来:1.可懂对象和被克隆对象的hashCode不同,属性值也不同,引用对象的hashCode也不一样, 属性值也不一样,说明两者互不影响

 

 

 TestClone以及引用对象完全不复制了一份,所以而知是互不影响的

四.序列化与反序列化实现深度克隆

 1 package com.design.clone.serialize;
 2 
 3 import java.io.Serializable;
 4 
 5 public class TestClone implements Serializable {
 6     private String testCloneName = "hello";
 7     private int testCloneInt = 0;
 8     private TestObj testObj = new TestObj();
 9 
10     public String getTestCloneName() {
11         return testCloneName;
12     }
13 
14     public void setTestCloneName(String testCloneName) {
15         this.testCloneName = testCloneName;
16     }
17 
18     public int getTestCloneInt() {
19         return testCloneInt;
20     }
21 
22     public void setTestCloneInt(int testCloneInt) {
23         this.testCloneInt = testCloneInt;
24     }
25 
26     public TestObj getTestObj() {
27         return testObj;
28     }
29 
30     public void setTestObj(TestObj testObj) {
31         this.testObj = testObj;
32     }
33 
34     @Override
35     public String toString() {
36         final StringBuilder sb = new StringBuilder("TestClone{");
37         sb.append("testCloneHashCode='").append(this.hashCode()).append('\'');
38         sb.append(",testCloneName='").append(testCloneName).append('\'');
39         sb.append(", testCloneInt=").append(testCloneInt);
40         sb.append(", testObjHashCode=").append(testObj.hashCode());
41         sb.append(", testObjInt=").append(testObj.getTestObjInt());
42         sb.append('}');
43         return sb.toString();
44     }
45 }
46 
47 
48 package com.design.clone.serialize;
49 
50 import java.io.Serializable;
51 
52 public class TestObj implements Serializable {
53     private int testObjInt = 1;
54 
55     public int getTestObjInt() {
56         return testObjInt;
57     }
58 
59     public void setTestObjInt(int testObjInt) {
60         this.testObjInt = testObjInt;
61     }
62 }
63 
64 package com.design.clone.serialize;
65 
66 import java.io.*;
67 
68 public class BeanUtils {
69 
70     public static Object clone(Object t) throws IOException, ClassNotFoundException {
71         ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
72         ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
73         objectOutputStream.writeObject(t);
74         objectOutputStream.flush();
75         ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
76         ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
77         return objectInputStream.readObject();
78     }
79 }
80 
81 package com.design.clone.serialize;
82 
83 import java.io.IOException;
84 
85 public class SerializeTest {
86     public static void main(String[] args) throws IOException, ClassNotFoundException {
87         TestClone testClone = new TestClone();
88         TestClone clone = (TestClone) BeanUtils.clone(testClone);
89         clone.setTestCloneInt(5);
90         clone.setTestCloneName("world");
91         clone.getTestObj().setTestObjInt(10);
92         System.out.println("被克隆对象testCone=" + testClone.toString());
93         System.out.println("克隆对象:" + clone.toString());
94     }
95 }

测试结果:结果也是互不影响

 

posted on 2020-03-31 22:51  楼子湾  阅读(224)  评论(0编辑  收藏  举报