原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 原型模式通过内存二进制流进行拷贝,不用经历对象初始化过程(不用调用构造函数);性能有所提升。
原型模式包括客户、抽象原型、具体原型3种角色:
客户:客户端提出创建对象的请求
抽象原型:规定拷贝接口
具体原型:被拷贝的对象
优点:
1、原型模式比基于二进制流拷贝,java自带的,比直接new一个对象性能性能好。
2、可以使用深克隆方式拷贝一个对象保存其状态,简化创建流程。需要的时候可以恢复到克隆保存的对象数据。可辅助实现撤销操作。
缺点:
1、需要对克隆的类配置一个方法。
2、克隆方法位于类的内部,当对已有类进行改造的时候,需要修改代码。违背开闭原则。
3、当对象有多重嵌套的时候,需要使用到深克隆使用比较麻烦。浅克隆对嵌套对象复制的只是一个引用地址。需权衡使用深克隆和浅克隆。
应用场景:
1、类初始化消耗资源较多
2、new产生的一个对象需要非常繁琐的过程(数据准备,访问权限等)
3、构造函数比较复杂
4、循环体中生产大量对象时。
代码示例:
浅克隆(实现Cloneable接口重写clone方法)
@Data
public class CloneEntity implements Cloneable{
private String name;
private List<String> names;
@Override
protected CloneEntity clone() throws CloneNotSupportedException {
return (CloneEntity)super.clone();
}
}
public static void main(String [] args){
try {
CloneEntity cloneEntity=new CloneEntity();
cloneEntity.setName("test");
List<String> list= new ArrayList<>();
list.add("zhangshan");
list.add("lisi");
cloneEntity.setNames(list);
System.out.println("-----------浅克隆-----------------");
CloneEntity clone = cloneEntity.clone();
clone.setName("clone_test");
clone.getNames().add("wangwu");
System.out.println("原对象:"+cloneEntity.toString());
System.out.println("浅克隆对象:"+clone.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
输出:
-----------浅克隆-----------------
原对象:CloneEntity(name=test, names=[zhangshan, lisi, wangwu])
浅克隆对象:CloneEntity(name=clone_test, names=[zhangshan, lisi, wangwu])
深克隆(通过序列化克隆)
@Data
public class CloneEntity implements Cloneable{
private String name;
private List<String> names;
public CloneEntity deepClone(){
try {
ByteArrayOutputStream bos=new ByteArrayOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(bos);
oos.writeObject(this);
ByteArrayInputStream bis=new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois=new ObjectInputStream(bis);
return (CloneEntity)ois.readObject();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public CloneEntity jsonClone(){
try {
String jsonObj= JSONObject.toJSONString(this);
return JSONObject.parseObject(jsonObj,this.getClass());
}catch (Exception e){
e.printStackTrace();
return null;
}
}
}
public static void main(String [] args){
try {
CloneEntity cloneEntity=new CloneEntity();
cloneEntity.setName("test");
List<String> list= new ArrayList<>();
list.add("zhangshan");
list.add("lisi");
cloneEntity.setNames(list);
System.out.println("-----------深克隆-----------------");
CloneEntity deepClone = cloneEntity.jsonClone();
deepClone.setName("clone_test");
deepClone.getNames().add("wangwu");
System.out.println("原对象:"+cloneEntity.toString());
System.out.println("浅克隆对象:"+deepClone.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
输出:
-----------深克隆-----------------
原对象:CloneEntity(name=test, names=[zhangshan, lisi])
浅克隆对象:CloneEntity(name=clone_test, names=[zhangshan, lisi, wangwu])
源码中应用案例
ArrayList实现了Cloneable接口(浅克隆)
public Object clone() {
try {
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(e);
}
}
HashMap实现了Cloneable接口(浅克隆)
public Object clone() {
HashMap<K,V> result;
try {
result = (HashMap<K,V>)super.clone();
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError(e);
}
result.reinitialize();
result.putMapEntries(this, false);
return result;
}
来源:oschina
链接:https://my.oschina.net/u/4483459/blog/3209911