Zer0e's Blog

设计模式之原型模式

字数统计: 897阅读时长: 3 min
2020/09/02 Share

前言

这篇来讲讲原型模式。

正文

概念

原型模式属于创建型模式,通常被用来创建重复的对象,通过原型来克隆对象,来获取相同的对象。
一般来说是创建对象的代价比较大时,比如对象的属性,设置较多,不方便重新创建,而是从原有对象进行拷贝。
这个模式实现的关键就是clone方法。
原型模式在实际项目中很少单独出现,通常是与工厂模式一起出现,由clone方法创建对象然后由工厂提供给调用者。

实现

我们依然用简单例子来讲讲这个模式。
首先创建的是抽象接口或者类。这里我采用是抽象类加实现Cloneable接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public abstract class Prototype implements Cloneable{
public String id;

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

abstract void test();

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

然后是具体的原型类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class ConcretePrototype1 extends Prototype{
public ConcretePrototype1() {
id = "1";
}

@Override
void test() {
System.out.println("id: " + id);
}
}
public class ConcretePrototype2 extends Prototype{
public ConcretePrototype2() {
id = "2";
}

@Override
void test() {
System.out.println("id: " + id);
}
}

接着我们创建一个管理类,帮助我们获取原型的克隆,相当于工厂模式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class PrototypeManager {
private static HashMap<String,Prototype> map = new
HashMap<>();
public static Prototype getPrototype(String id){
Prototype prototype = map.get(id);
return (Prototype) prototype.clone();
}

public static void init(){
ConcretePrototype1 concretePrototype1 = new ConcretePrototype1();
map.put(concretePrototype1.getId(),concretePrototype1);

ConcretePrototype2 concretePrototype2 = new ConcretePrototype2();
map.put(concretePrototype2.getId(), concretePrototype2);
}
}

最后我们实现一个客户端调用看看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Client {
public static void main(String[] args) {
PrototypeManager.init();

Prototype clonePrototype1 = PrototypeManager.getPrototype("1");
clonePrototype1.test();

Prototype clonePrototype1_ = PrototypeManager.getPrototype("1");
clonePrototype1_.test();

System.out.println(clonePrototype1.hashCode() + " " + clonePrototype1_.hashCode());

}
}

那最后一行输出是为了看两个对象是否相同,如果是同一个对象那么hashcode应该是相同的,那结果很明显是不同的,所以两个对象只是属性相同,而在内存中的引用不同。
如此我们就结合了原型模式和工厂模式。当然,对于原型管理器也就是PrototypeManager应该实现动态的添加和删除原型,即应该实例化这个对象,并且加上锁来实现并发,这里就不再实现了。

Java中的克隆

这里有一点要说的是,Cloneable接口只起一个作用,并没有实际的方法,它的目的只是告诉JVM可以在这个类上安全的使用clone方法,如果没有实现这个接口,则会抛出CloneNotSupportedException异常。

优缺点

最后我们依旧来讲讲这个模式的优缺点。
优点呢,在于性能高效,并且如果构造函数十分复杂的话还可以不用理会,因为可以直接克隆。
那缺点也十分明显,需要实现cloneable接口,其次就是每个类都必须有一个克隆方法,因为不是所有的类都可以直接使用父类clone方法来进行克隆,复杂的类也许需要手动重新clone方法。然后还有就是在进行拷贝的时候,有可能会出现循环引用的场景,导致栈溢出也是有可能的,因此clone方法并不一定好用。

总结

以上就是关于原型模式的内容。感觉容量不大,但是需要手动写写代码才能更好的理解。

CATALOG
  1. 1. 前言
  2. 2. 正文
    1. 2.1. 概念
    2. 2.2. 实现
    3. 2.3. Java中的克隆
    4. 2.4. 优缺点
  3. 3. 总结