一、引言
在开发过程中,有时会遇到为一个类创建多个实例的情况,这些实例内部成员往往完全相同或有细微的差异,而且实例的创建开销比较大或者需要输入较多参数,如果能通过复制一个已创建的对象实例来重复创建多个相同的对象,这就可以大大减少创建对象的开销,这个时候就需要原型模式。
二、模式详解
1、模式分析
原型模式可以通过一个对象实例确定创建对象的种类,并且通过拷贝创建新的实例。总得来说,原型模式实际上就是从一个对象创建另一个新的对象,使新的对象有具有原对象的特征。
图1给出了原型模式的UML图,可以看出原型模式的结构非常简单。首先,所有可以作为原型的类中都应该有一个用于复制自身的方法clone(),因此,我们可以抽象出一个抽象原型类或接口,该类中只有一个clone(),所有的具体原型类都要实现该方法并定义复制自身的具体行为。在客户端中通过调用具体原型对象的clone方法可以复制原型对象到一个新的对象中。
2、具体实现
利用jdk的 Cloneable 接口
浅复制:
public class Prototype implements Cloneable {
public String name;
CloneTarget target = null;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
深复制:
猴子类
public class Monkey {
public int height;
public int weight;
public Date birthday;
}
金箍棒类
public class JinGuBang implements Serializable {
public float h = 100;
public float d = 10;
public void big(){
this.d *= 2;
this.h *= 2;
}
public void small(){
this.d /= 2;
this.h /= 2;
}
}
齐天大圣类:
public class QiTianDaSheng extends Monkey implements Cloneable,Serializable {
public JinGuBang jinGuBang;
public QiTianDaSheng(){
//只是初始化
this.birthday = new Date();
this.jinGuBang = new JinGuBang();
}
@Override
protected Object clone() throws CloneNotSupportedException {
return this.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.birthday = new Date();
return copy;
}catch (Exception e){
e.printStackTrace();
return null;
}
}
测试类:
public class Main {
public static void main(String[] args) {
QiTianDaSheng q = new QiTianDaSheng();
QiTianDaSheng n = q.copy(q);
System.out.println(q.jinGuBang == n.jinGuBang);
}
}
运行结果: