最近学习到设计模式,现总结个人学习原型模式内容。
上一篇:Java设计模式-工厂模式
定义
用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。理解:通过复制的方式创建新的对象。原型模式明显更关心的是结果的一致性。
优缺点
优点
- 向客户隐藏制造新实例的复杂性【用户对对象的创建过程不可见】
- 在某些环境下,复制对象比创建新对象更有效【举例流程表单的流程对象】
例如这个实体类,就成员都将近150个,如果全都通过创建对象的方式,其工作量是不可估量的。
缺点
- 需要为被克隆的目标类添加克隆方法,当对已有类进行改造的时候,需要修改代码,违反了开闭原则。
- 在实现深克隆【深拷贝】时需要编写较为复杂的代码,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来会比较麻烦。
实现
先给定两个实体类
class Money implements Serializable,Cloneable{
private static final long serialVersionUID = -4350061171177220007L;
public String moneytype;
public Double moneynum;
Money(String moneytype,Double moneynum){
this.moneytype=moneytype;
this.moneynum=moneynum;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class UserEntity implements Serializable,Cloneable{
private static final long serialVersionUID = 1L;
private String name;
private int age;
private ArrayList<String> phonenumbers ;
private ArrayList<Money> moneys ;
private Money moeny;
}
浅拷贝
利用Object的clon方法
代码实现
/**
* 浅拷贝仅能拷贝八大基本数据类型+String
* 数据类型,其他数据类型直接引用地址
* 例如这里拷贝不了用户的电话号码集合
* @return
*/
public UserEntity getShallowCopy(){
UserEntity copyentity = null;
try {
copyentity= (UserEntity) this.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return copyentity;
}
测试
可以看到对拷贝后的数据进行修改,其中修改基本类型+String类型并没有影响到原始数据,但是对对象修改明显影响到 原始数据。这个就需要说到深拷贝的实现了,需要自己对对象的所有成员,进行递归式的浅拷贝。
深拷贝
代码实现
/**
* 深拷贝,在浅拷贝了基本类型+String数据后,
* 需要对引用类型单独进行拷贝。但是如果引用类型中还存在引用依然非完全深拷贝
* @return
*/
public UserEntity getDeepCopy(){
UserEntity copyentity = null;
try {
copyentity= (UserEntity) this.clone();
copyentity.phonenumbers = (ArrayList<String>) this.phonenumbers.clone();
copyentity.moneys = (ArrayList<Money>) this.moneys.clone();
copyentity.moeny = (Money) this.moeny.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return copyentity;
}
测试
从测试结果中,我们以及看到深拷贝需要对每一个成员中的对象进行克隆,同时自定义对象也需要实现clon方法,但是为什么对
字节码拷贝
代码实现
* 利用序列化与反序列化实现
* @return
*/
public UserEntity getByteCopy(){
ByteArrayOutputStream baos = null;
ObjectOutputStream oos = null;
ByteArrayInputStream bais = null;
ObjectInputStream ois = null;
UserEntity copyentity = null;
try {
//序列化
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject(this);
//反序列化
bais = new ByteArrayInputStream(baos.toByteArray());
ois = new ObjectInputStream(bais);
copyentity = (UserEntity)ois.readObject();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
oos.close();
baos.close();
bais.close();
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return copyentity;
}
测试
日常对较大对象的拷贝尽量使用原型模式的方式,降低创建对象成本,较大对象的创建需要耗费cpu网络等,较大引起gc回收。
以上仅为个人学习,如果错误望指出,谢谢。