设计模式(9)——原型模式
本文介绍原型模式的概念和应用。
# 基本思想和原则
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
# 动机
当我们需要创建大量对象时,如果用传统的 new 一个对象的方式,在效率上会比较低,因为类的初始化过程开销较大,我们可以通过直接拷贝一个对象来获得一个新对象。另外在多线程场景下,由于在同一个对象上操作为了保证线程安全就需要加锁,降低了并发性能,这时我们一般希望产生不同对象进行操作。这些场景都是原型模式的适用场景。
# 实现
public class Minion implements Cloneable {
private int id;
public Minion(int id) {
this.id = id;
}
public void sing() {
System.out.println("Ba-ba-ba, Ba-banana. Ba-ba-ba, Ba-banana~");
}
public void eat() {
System.out.println("Minion eat!");
}
public void sleep() {
System.out.println("Minion sleep!");
}
public void setId(int id) {
this.id = id;
}
public int getId() {
return this.id;
}
@Override
public Minion clone() {
Minion minion = null;
try {
minion = (Minion)super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return minion;
}
}
public class Test {
public static void main(String[] args) {
int count = 10;
Minion minion = new Minion(0);
for (int i = 0; i < count; i++) {
Minion cloneMinion = minion.clone();
cloneMinion.setId(i);
System.out.print("Minion " + cloneMinion.getId() + " is singing: ");
cloneMinion.sing();
}
}
}
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
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
输出如下:
Minion 0 is singing: Ba-ba-ba, Ba-banana. Ba-ba-ba, Ba-banana~
Minion 1 is singing: Ba-ba-ba, Ba-banana. Ba-ba-ba, Ba-banana~
Minion 2 is singing: Ba-ba-ba, Ba-banana. Ba-ba-ba, Ba-banana~
Minion 3 is singing: Ba-ba-ba, Ba-banana. Ba-ba-ba, Ba-banana~
Minion 4 is singing: Ba-ba-ba, Ba-banana. Ba-ba-ba, Ba-banana~
Minion 5 is singing: Ba-ba-ba, Ba-banana. Ba-ba-ba, Ba-banana~
Minion 6 is singing: Ba-ba-ba, Ba-banana. Ba-ba-ba, Ba-banana~
Minion 7 is singing: Ba-ba-ba, Ba-banana. Ba-ba-ba, Ba-banana~
Minion 8 is singing: Ba-ba-ba, Ba-banana. Ba-ba-ba, Ba-banana~
Minion 9 is singing: Ba-ba-ba, Ba-banana. Ba-ba-ba, Ba-banana~
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
上面的代码中定义了一个“小黄人”类Minion
,需要产生大量小黄人,这里可以使用原型模式。我们将Minion
类实现了Cloneable
接口,如果去查看Cloneable
接口,会发现这个接口里实际上没有任何方法:
public interface Cloneable {
}
1
2
2
很奇怪吧?那么这个clone
方法从何而来呢?在Object
类中我们找到下面的代码:
protected native Object clone() throws CloneNotSupportedException;
1
可以看出clone
方法是从Object
类继承而来的,Java 中几乎所有对象都是继承自Object
类,另外@Override
修饰也说明了clone
方法是继承而来的。所以Cloneable
接口只是简单地标记一个类可以调用clone
方法。
需要注意的是,拷贝分为浅拷贝和深拷贝。上面这种方式是浅拷贝,浅拷贝的意思是只复制基本类型的数据,对于引用数据,比如数组、集合、哈希表或其他类的实例对象,只复制引用。如果要实现深拷贝,需要自行在clone
方法中对响应对象做拷贝操作。
# 优点
原型模式在需要大量产生对象的时候比直接 new 一个对象性能上更好,类初始化的时候比较耗费资源,原型模式是直接在内存中通过拷贝二进制数据来获得一个新对象,因此性能上占优势。而且原型模式在拷贝时不会调用构造函数,这在某些时候有一定用处。
编辑 (opens new window)
上次更新: 2024-07-15, 03:27:09