原型模式
1:模式定义
根据原对象实例复制新的实例。
2:实现方式
- 浅拷贝:使用一个已知实例对新创建实例的成员变量逐个赋值(可以理解为两个对象实例地址不一样,但是字段的地址一样。打个比方10个猴子拿着的是同一根金箍棒)
//直接实现一个cloneable接口就完成了浅拷贝
public class Monkey implements Cloneable {
public String name;
public ArrayList<String> list=new ArrayList<>();
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
- 深拷贝:当一个类的拷贝构造方法,不仅要复制对象的所有非引用成员变量值,还要为引用类型的成员变量创建新的实例,并且初始化为形式参数实例值.
//金箍棒
public class JinGuBang implements Serializable{
private int h;
private int d;
}
//猴子
public class Monkey {
public int height;
public int weight;
public Date bitrhday;
}
public class QiTianDaSheng extends Monkey implements Cloneable ,Serializable{
public JinGuBang jinGuBang;
public QiTianDaSheng(){
//初始化
this.bitrhday=new Date();
this.jinGuBang=new JinGuBang();
}
@Override
protected Object clone() throws CloneNotSupportedException {
//浅复制和深复制的区别
// return super.clone();
return deepClone();
}
/*
深复制的一种实现 利用序列化的方式
还有反射的形式,性能差。
* */
public Object 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);
QiTianDaSheng copy =(QiTianDaSheng)ois.readObject();
copy.bitrhday=new Date();
return copy;
}catch (Exception e){
e.printStackTrace();
return null;
}
}
}
3:模式优缺点分析
优点:
- 若创建的对象比较复杂,利用原型模式可以大大提高创建对象的效率。
- 可以使用深克隆方式保存对象的状态,使用原型模式将对象复制一份并将其状态保存起来,以便在需要的时候使用(例如恢复到历史某一状态),可辅助实现撤销操作。
- 可以使用深克隆保持对象的状态。
缺点:
- 在实现深克隆的时候比较复杂,可能使用反射或者序列化或者其他方式。
4:使用场景分析
- apach的beanutils包 用来拷贝属性的(通过反射实现)
- spring 的原型模式(scope=prototype),有兴趣可以看下源码