原型模式学习笔记
通过一个原型对象克隆出多个一模一样的对象,该模式称之为原型模式。
定义:使用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。原型模式是一种对象创建型模式。
通过克隆所创建的对象是全新的对象,创建克隆对象的工厂就是原型类自身,工厂方法由克隆方法实现。
原型模式结构图 如下图所示:
在原型模式中包含如下几个角色:
抽象原型类,声明克隆方法的接口,是所有具体原型类的公共父类。
具体原型类:实现再抽象原型类中声明的克隆方法,在克隆方法中返回自己的一个克隆对象。
class ConcreteProtoType implements ProtoType {
private String attr;
public void setAttr(String attr) {
this.attr = attr;
}
public String getAttr() {
return this.attr;
}
public ProtoType clone() {
ProtoType protoType = new ConcreteProtoType();
protoType.setAttr(this.attr);
return protoType;
}
}
在Java中对于所有的对象都是有一个共同父类Object的,而Object类已经声明了clone方法接口的,因为我们对于需要实现克隆方法的直接调用父类的clone方法就好,只需要在实现克隆类的时候实现Cloneable接口,即表示这个Java类支持被克隆。如下:
class ConcreteType implements Cloneable {
....
public ProtoType clone() {
Object object = null;
try {
object = super.clone();
} catch (CloneNotSupportedException exception) {
/*handle the exception*/
}
return (ProtoType)object;
}
}
class Client {
public static void main(String args[]) {
ProtoType obj1 = new ConcreteProtoType();
ProtoType obj2 = obj1.clone();
/*此时obj1和obj2是完全相同的*/
}
}
通过以上的方法就可以实现类的克隆。
但是在生产过程中发现如果类的成员含有的不只有基本类型的话,如果还含有其他类对象的话,就会导致问题。这里涉及到深拷贝和浅拷贝的概念。
对于浅拷贝,只是简单的将类的数据拷贝,即在内存中复制一份相同的数据而已,那如果还有别的类对象的话就会出现克隆类和原型类都含有对象的共同引用,而不是真正意义上的克隆。这里就需要是用深拷贝,即在克隆的时候对于每一个类成员变量都会进行递归的进行克隆,那么这时候克隆类里所有的内容都和原类的内容一样,但是地址完全不相同。
而为了实现深拷贝,那么克隆类就需要实现接口Serializable,即表明该Java类是支持深拷贝的(序列化)。代码如下:
class WeeklyLog implements Serializable {
private Attachment attachment;
private String name;
public void setAttachment(Attachment attachment) {
this.attachment = attachment;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
public Attachment getAttachment() {
return this.attachment;
}
public WeeklyLog deepClone throws RuntimeException {
ByteArrayOutputStream memoryBuffer = new ByteArrayOutputStream();
ObjectOutputStream out= new ObjectOutputStream(memoryBuffer);
out.writeObject(this);
ObjectInputStream in = new ObjectArrayInputStream(new ByteArrayOutputStream(memoryBuffer.toByteArray()));
return (WeeklyLog)in.readObject();
}
}
通过序列化的方式就可以实现所谓的深拷贝,克隆出来的数据内容都是一样的,但是对象的地址完全不一样。
另外有一种所谓的原型管理器的概念,即将系统中所有需要使用原型模式进行克隆的类都放入管理器,客户端调用的时候直接传入需要克隆的参数,管理器会根据参数克隆出新的对象返回。
总结:
当需要创建的对象消耗很大的资源,诸如初始化时间长或者需要网络资源/CPU资源等,那么这时候就可以考虑使用原型模式,使用一个原本就存在的对象直接进行复制得到,这样子可以很大的提高效率。如果系统中需要对某个对象的状态进行保存,那么这时候就可以使用原型模式。
为了实现原型模式,类必须实现Clone接口或者Serializable接口,对于深拷贝的话还得修改每一层类的深克隆,实现起来较麻烦。