设计模式之原型模式

简介:

原型模式是创建型设计模式之一,这是一个克隆原型产生实例的设计,主要用于解决复杂创建的对象或者构建耗时的对象。

UML类图


从UML图中我们可以看到,原型模式的实现其实很简单,主要是将所需要实现原型模式的对象去实现Cloneable接口,然后去重写它的clone()方法

案例讲解

同样,我们以Retrofit框架为例,讲解一下别人是如何使用这个设计模式的,那么我们看到Call这个接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public interface Call<T> extends Cloneable {
Response<T> execute() throws IOException;
void enqueue(Callback<T> callback);
boolean isExecuted();
void cancel();
boolean isCanceled();
Call<T> clone();
Request request();
}

我们看到这个Call接口实现了Cloneable,那么实现它的原型有 OkHttpCall 和 ExecutorCallbackCall,然后我们通过他们的源码发现,他们并没有调用super.clone()

1
2
3
4
@SuppressWarnings("CloneDoesntCallSuperClone") // We are a final type & this saves clearing state.
@Override public OkHttpCall<T> clone() {
return new OkHttpCall<>(serviceMethod, args);
}

这是OkHttpCall实现的clone,是不是发现这所谓的原型模式,怎么不对,怎么变成new一个对象,那么我们为啥还使用clone方法去获取一个对象呢,直接new一个不就行了吗,这里我们看到它用SuppressWarnings注解对警告进行了忽略,然后我们看下它的注释,原来这是保存了这个类的最终状态,避免其它调用者进行修改而做的保护性拷贝,我们再看看另一个

1
2
3
4
@SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone.
@Override public Call<T> clone() {
return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());
}

这里同样是通过new构建的一个对象,注解表示它进行了一个深拷贝,什么是深拷贝呢?
我们看到这个OkHttpCall将serviceMethod和args传入进去,这两个都是对象类型,那么这两个值一旦发生变化,相应的原型内的值也会发生变化,因此这种拷贝叫浅拷贝,如果是深拷贝呢,那么副本修改过的则不会影响到原型的值。
那么我们这里看到传入的两个参数都是接口,而有可能发生改变的则是Call回调接口,使用这里用了delegate.clone()来保证新创建的ExecutorCallbackCall不会影响到其它ExecutorCallbackCall。