设计模式—原型模式

定义

用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象

代码

原型的核心就是通过clone() 方法来创建对象

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
public class Thing implements Cloneable {

private String name;
private List<String> addressList = new ArrayList<>();

public Thing() {
System.out.println("构造函数执行了");
}

@Override
protected Thing clone() {
Thing thing =null;
try {
thing = (Thing) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return thing;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public List<String> getAddressList() {
return addressList;
}

public void setAddressList(String address) {
this.addressList.add(address);
}
}

上面的原型类实现了Cloneable 接口,并重写了clone 方法。

测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class ThingTest {

public static void main(String[] args) {
Thing thing = new Thing();
thing.setName("游戏");
thing.setAddressList("北京");
//构造函数不执行
Thing thing2 = thing.clone();
thing2.setName("读书");
//String 更改不影响原型
System.out.println(thing.getName()+"--"+thing2.getName());
thing2.setAddressList("上海");
System.out.println(thing2.getAddressList());
//浅拷贝 原型list内容变化了
System.out.println(thing.getAddressList());

}
}

由测试结果可以看到,拷贝的时候构造函数不执行 并且 引用的全局变量(不包括String)在clone的时候是浅拷贝,只是拷贝了其引用地址,这是需要改变下原型的clone方法来进行深拷贝

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
public class Thing implements Cloneable {

private String name;
private ArrayList<String> addressList = new ArrayList<>();

public Thing() {
System.out.println("构造函数执行了");
}

@Override
protected Thing clone() {
Thing thing =null;
try {
thing = (Thing) super.clone();
thing.addressList = (ArrayList<String>) this.addressList.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return thing;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public List<String> getAddressList() {
return addressList;
}

public void setAddressList(String address) {
this.addressList.add(address);
}
}

List 声明改成ArrayList,并在clone方法里将addressList进行clone,这时候再去运行测试代码就发现addressList的内容就不相互影响了。