本节来讲原型模式在 JDK 源码中的应用。首先查看 JDK 中的 Cloneable 接口。
public interface Cloneable {
}
我们只需要在源码中看哪些类实现了 Cloneable 接口即可。下面是 ArrayList 类的实现代码。
public Object clone() {
try {
@SuppressWarnings("unchecked")
ArrayList v = (ArrayList) super.clone();
v.elementData = Arrays.copyOf(elementData, size);
v.modCount = 0;
return v;
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError();
}
}
从以上代码可以看出,clone() 方法只是将 List 中的元素循环遍历了一遍。此时,再思考一下,是不是这种形式就是深克隆呢?
下面用代码验证一下,继续修改 ConcretePrototype 类,增加一个 deepCloneHobbies() 方法,代码如下:
public class ConcretePrototype implements Cloneable,Serializable {
public ConcretePrototype deepCloneHobbies(){
try {
ConcretePrototype result = (ConcretePrototype) super.clone();
result.hobbies = (List) ((ArrayList) result.hobbies).clone();
return result;
}catch (CloneNotSupportedException){
return null;
}
}
...
}
客户端代码修改如下:
public static void main(String[] args) {
...
//复制原型对象
ConcretePrototype cloneType = prototype.deepCloneHobbies();
...
}
运行结果如下:
原型对象:ConcretePrototype{age=18,name='C语言中文网',hobbies=[书法, 美术]}
克隆对象:ConcretePrototype{age=18,name='C语言中文网',hobbies=[书法, 美术, 技术控]}
可以发现以上结果与《使用序列化实现深克隆》一节运行结果相同,说明以上形式是深克隆。但是这样的代码是硬编码。如果在对象中声明了各种集合类型,则每种情况都需要单独处理。因此,深克隆的写法一般会直接用序列化来操作。