简介:
原型模式是创建型设计模式之一,这是一个克隆原型产生实例的设计,主要用于解决复杂创建的对象或者构建耗时的对象。
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") @Override public OkHttpCall<T> clone() { return new OkHttpCall<>(serviceMethod, args); }
|
这是OkHttpCall实现的clone,是不是发现这所谓的原型模式,怎么不对,怎么变成new一个对象,那么我们为啥还使用clone方法去获取一个对象呢,直接new一个不就行了吗,这里我们看到它用SuppressWarnings注解对警告进行了忽略,然后我们看下它的注释,原来这是保存了这个类的最终状态,避免其它调用者进行修改而做的保护性拷贝,我们再看看另一个
1 2 3 4
| @SuppressWarnings("CloneDoesntCallSuperClone") @Override public Call<T> clone() { return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone()); }
|
这里同样是通过new构建的一个对象,注解表示它进行了一个深拷贝,什么是深拷贝呢?
我们看到这个OkHttpCall将serviceMethod和args传入进去,这两个都是对象类型,那么这两个值一旦发生变化,相应的原型内的值也会发生变化,因此这种拷贝叫浅拷贝,如果是深拷贝呢,那么副本修改过的则不会影响到原型的值。
那么我们这里看到传入的两个参数都是接口,而有可能发生改变的则是Call回调接口,使用这里用了delegate.clone()来保证新创建的ExecutorCallbackCall不会影响到其它ExecutorCallbackCall。