原型模式

原型模式

属于创建者模式

原型对象负责创建需要用到的对象, 使用者直接拷贝原型,作为创建的对象

注意, 是拷贝, 不是引用; 核心点是object对象的clone方法

为什么要使用原型模式

  1. 使用原型模式拷贝对象, 可以获得对象的运行状态, 不会产生一个初始全新对象
  2. 拷贝的效率比创建的效率更高
  3. 一个对象有多个访问者的时候,可以考虑用原型模式
  4. 对于一个创建过程很复杂的类来说, 可以使用原型模式

使用原型模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
//原型类
// 实现拷贝需要继承Cloneable接口
public class Sheep implements Cloneable, Serializable {
@Override
public String toString() {
return "Sheep{" +
"name='" + name + '\'' +
", master=" + master +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Master getMaster() {
return master;
}
public void setMaster(Master master) {
this.master = master;
}
private String name;
private Master master;


@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}

// 把引用的对象也进行拷贝
// 这种方法要把所有要拷贝的类都继承Cloneable,并且当有多层引用关系时, 代码会很复杂
// 不推荐
public Object deepCloneAbandon() throws CloneNotSupportedException {
Sheep clone=(Sheep) super.clone();
clone.master=(Master) this.master.clone();
return clone;
}

// 用流的方法实现深拷贝, 推荐使用
public Object deepClone() throws CloneNotSupportedException {
ByteArrayOutputStream byteArrayOutputStream = null;
ObjectOutputStream objectOutputStream = null;
ByteArrayInputStream byteArrayInputStream = null;
ObjectInputStream objectInputStream = null;
try {
byteArrayOutputStream = new ByteArrayOutputStream();
objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(this);

byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
objectInputStream = new ObjectInputStream(byteArrayInputStream);
return objectInputStream.readObject();
} catch (IOException iOException) {
iOException.printStackTrace();
return null;
} catch (ClassNotFoundException classNotFoundException) {
classNotFoundException.printStackTrace();
return null;
} finally {
try {
byteArrayOutputStream.close();
objectOutputStream.close();
byteArrayInputStream.close();
objectInputStream.close();
} catch (IOException iOException) {
iOException.printStackTrace();
}
}
}
}

//测试
@Test
public void testPrototype() throws CloneNotSupportedException {
Sheep sheep = new Sheep();
sheep.setName("喜洋洋");
sheep.setMaster(new Master("村长"));
Sheep copysheep = (Sheep) sheep.clone();
// hashCode不同,说明不是复制引用而是拷贝对象
// 拷贝对象中的属性为引用类型的时候, 拷贝的引用地址
// 所以默认的clone方法是浅拷贝的方法
System.out.println(sheep.hashCode() + " " + sheep.toString());
System.out.println(copysheep.hashCode() + " " + copysheep.toString());

// 人工再拷贝实现深拷贝
System.out.println("人工再拷贝实现深拷贝");
Sheep deepCopySheepAbandon = (Sheep) sheep.deepCloneAbandon();
System.out.println(deepCopySheepAbandon.hashCode() + " " + deepCopySheepAbandon.toString());

// 用流深拷贝
System.out.println("用流深拷贝");
Sheep deepCopySheep = (Sheep) sheep.deepClone();
System.out.println(deepCopySheep.hashCode() + " " + deepCopySheep.toString());
}

Spring中应用

bean的scope属性可以指定为prototype原型模式, 每次创建bean时都是clone创建;

注意(缺点)

在实现深度克隆时, 代码复杂
需要给每个类写克隆方法, 对于已有不支持clone的类,工作量大,而且违背了开闭原则