原型模式的各角色定义如下
● Prototype(原型接口):声明克隆方法,对应本例程代码中的Cloneable接口。
● ConcretePrototype(原型实现):原型接口的实现类,实现方法中调用super.clone()即可得到新克隆的对象。
● Client(客户端):客户端只需调用实现此接口的原型对象方法clone(),便可轻松地得到一个全新的实例对象。
从类到对象叫做“创建”, 从实例对象到副本对象叫做“克隆”
使用场景
当需要创建多个类似的复杂对象时,可以考虑原型模式,克隆操作只会进行内存操作,直接拷贝原型对象数据流生成新的副本对象,不会触发一些复杂操作(初始化),效率远远大于‘new’ 关键字触发的实例化操作
浅拷贝/深拷贝
浅拷贝:只复制原始类型的值
深拷贝:不只复制原始类型的值,引用对象也拷贝
实现细节
原型对象和引用对象都需要实现 java.lang.Cloneable 接口, 重写 clone() 方法
public class PrototypeDemo implements Cloneable{
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
浅拷贝
深拷贝
区别主要在于:在原型对象的clone() 方法中是否克隆引用对象?
@Override
protected PrototypeDemo clone() throws CloneNotSupportedException {
PrototypeDemo prototypeDemo = (PrototypeDemo) super.clone();
// 是否克隆引用对象
prototypeDemo.setSubPrototypeDemo(subPrototypeDemo.clone());
return prototypeDemo;
}
实例代码如下
package com.azure.design.prototype;
/**
* 原型类
*/
public class PrototypeDemo implements Cloneable{
private String name;
private SubPrototypeDemo subPrototypeDemo = new SubPrototypeDemo("引用类");
public PrototypeDemo(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public SubPrototypeDemo getSubPrototypeDemo() {
return subPrototypeDemo;
}
public void setSubPrototypeDemo(SubPrototypeDemo subPrototypeDemo) {
this.subPrototypeDemo = subPrototypeDemo;
}
public PrototypeDemo(String name, SubPrototypeDemo subPrototypeDemo) {
this.name = name;
this.subPrototypeDemo = subPrototypeDemo;
}
@Override
public String toString() {
return "PrototypeDemo{" +
"name='" + name + '\'' +
", subPrototypeDemo=" + subPrototypeDemo +
'}';
}
@Override
protected PrototypeDemo clone() throws CloneNotSupportedException {
PrototypeDemo prototypeDemo = (PrototypeDemo) super.clone();
prototypeDemo.setSubPrototypeDemo(subPrototypeDemo.clone());
return prototypeDemo;
}
}
package com.azure.design.prototype;
/**
* 引用类
*/
public class SubPrototypeDemo implements Cloneable{
private String subName;
public SubPrototypeDemo(String subName) {
this.subName = subName;
}
public String getSubName() {
return subName;
}
public void setSubName(String subName) {
this.subName = subName;
}
@Override
public String toString() {
return "SubPrototypeDemo{" +
"subName='" + subName + '\'' +
'}';
}
@Override
protected SubPrototypeDemo clone() throws CloneNotSupportedException {
return (SubPrototypeDemo) super.clone();
}
}
package com.azure.design.prototype;
/**
* 克隆工厂类
*/
public class PrototypeFactory {
// 使用 懒汉模式 创建一个 PrototypeDemo 对象
private static PrototypeDemo prototypeDemo =
new PrototypeDemo("原型",new SubPrototypeDemo("引用类"));
/**
* 对外暴露克隆的方法
* 参数克隆对象名
* @param name
* @return
*/
public static PrototypeDemo getCloneInstance(String name) throws CloneNotSupportedException {
System.out.println("拷贝前" + prototypeDemo + "," + prototypeDemo.getSubPrototypeDemo());
// 克咯对象
PrototypeDemo subPrototypeDemo = prototypeDemo.clone();
subPrototypeDemo.setName(name);
// System.out.println("浅拷贝后" + subPrototypeDemo + "," + subPrototypeDemo.getSubPrototypeDemo());
System.out.println("深拷贝后" + subPrototypeDemo + "," + subPrototypeDemo.getSubPrototypeDemo());
return subPrototypeDemo;
}
}