设计模式 - 原型模式
原型模式:通过拷贝原型实例,生成一个新的对象(java中,多专指实现Cloneable接口对象)
实现原理:
- clone的实现是在内存中直接拷贝二进制流,无需经过构造函数(native方法,上帝后门)。
- 通过cloneable接口标记对象是否有权触发object.clone()方法。
优点:
- clone方法直接操作内存拷贝二进制流,性能优越。
- 不需要经过构造函数等,避免了构造函数中的约束。
应用场景:
- 性能和资源优化:类初始化需要消费非常多资源,在需要创建大量重复的类时。
- 跳过校验的场景:当创建类需要做非常繁琐的数据准备和检验时。
- 对象需要被分享时:一个对象被多个访问者同时访问时,通过拷贝避免共享干扰。
浅复制:clone方法是对内存中的二进制流做复制,所以,当对象属性中存在引用对象时,只复制引用
clone的一般实现
浅克隆(Cloneable)
// java自带cloneable接口浅克隆 - 通过内存二进制流复制实现
@Override
public PrototypeMember clone(){
try {
return (PrototypeMember)super.clone();
} catch (CloneNotSupportedException e){
e.printStackTrace();
return null;
}
}
深克隆(Cloneable)
// java自带cloneable,通过递归将所有引用属性都进行clone后实现深克隆
public PrototypeMember deepcloneByCloneable(){
try {
PrototypeMember prototypeMember = (PrototypeMember)super.clone();
// java为集合中大部分的实现类提供了clone方法的浅复制实现
prototypeMember.list = (List)((ArrayList)list).clone();
return prototypeMember;
} catch (CloneNotSupportedException e){
e.printStackTrace();
return null;
}
}
扩展 - 序列化实现深克隆(Serializable)
- 只有实现了Serializable接口的类才可以序列化和反序列化
- 反序列化时:会在继承链中,找到离实际对象最近的一个没有实现Serializable接口的父类,并调用其构造方法
- 实际的创建过程应该是 未实现Serializable接口的父类的构造方法 与 实现了Serializable接口的子类的ObjectStreamClass(描述了class对象结构),一同完成对象的创建。
// java自带Serializable,通过obj序列化成字节数组,再反序列实现clone
public PrototypeMember deepCloneBySerializable(){
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 (PrototypeMember) ois.readObject();
} catch (Exception e){
e.printStackTrace();
return null;
}
}
扩展 - 反射复制
- json的实现方法即为反射,需要调用对象类的构造函数(所以性能并没有提升)
// 使用反射完成clone浅克隆
public PrototypeMember cloneByReflect(){
try {
Class clazz = this.getClass();
PrototypeMember result = (PrototypeMember)clazz.newInstance();
for(Field filed : clazz.getDeclaredFields()){
filed.setAccessible(true);
filed.set(result,filed.get(this));
}
return result;
} catch (Exception e){
e.printStackTrace();
return null;
}
}
// 使用json实现深克隆
public PrototypeMember deepCloneByJSON(){
String json = JSONObject.toJSONString(this);
return JSON.parseObject(json,PrototypeMember.class);
}
欢迎疑问、期待评论、感谢指点 -- kiqi,愿同您为友
-- 星河有灿灿,愿与之辉