原型模式简单来说就是自身拷贝的过程,分为浅拷贝和深拷贝。一般需要一个抽象接口Prototype有一个clone方法,实现类调用此方法就可以实现对象拷贝。这就可以使用Object的clone方法,只不过需要实现Cloneable接口并将clone覆盖为public的。
public abstract class Prototype<T> implements Cloneable,Serializable{
public int prop1=1;
public String prop2="2";
@Override
public T clone() throws CloneNotSupportedException {
return (T)super.clone();
}
}
public class ConcretePrototype1 extends Prototype<ConcretePrototype1> {
@Override
public String toString() {
return "ConcretePrototype1{prop1=" + prop1 +", prop2=" + prop2 +'}';
}
}
写个测试方法
private static void testClone() throws CloneNotSupportedException {
ConcretePrototype1 p1=new ConcretePrototype1();
ConcretePrototype1 c1=p1.clone();
System.out.println("p1:"+p1);
System.out.println("c1:"+c1);
System.out.println("p1.prop2==c1.prop2 is "+(p1.prop2==c1.prop2));
}
结果为:
p1:ConcretePrototype1{prop1=1, prop2=2}
c1:ConcretePrototype1{prop1=1, prop2=2}
p1.prop2==c1.prop2 is true
可以看到这种方式实现的拷贝对于对象属性只是复制了对象的引用,所以这种方式是浅拷贝。下面我们利用对象的序列化与反序列化实现对象的深拷贝。
public class ConcretePrototype2 extends Prototype<ConcretePrototype2> {
@Override
public ConcretePrototype2 clone() throws CloneNotSupportedException {
ByteArrayOutputStream bytes=new ByteArrayOutputStream();
try {
ObjectOutputStream os=new ObjectOutputStream(bytes);
os.writeObject(this);
ByteArrayInputStream bais=new ByteArrayInputStream(bytes.toByteArray());
ObjectInputStream is=new ObjectInputStream(bais);
return (ConcretePrototype2)is.readObject();
} catch (Exception e) {
throw new CloneNotSupportedException(e.getMessage());
}
}
}
测试用例:
private static void testDeepClone() throws CloneNotSupportedException {
ConcretePrototype2 p2=new ConcretePrototype2();
ConcretePrototype2 c2=p2.clone();
System.out.println("p2:"+p2);
System.out.println("c2:"+c2);
System.out.println("p2.prop2==cc.prop2 is "+(p2.prop2==c2.prop2));
}
结果:
p2:com.pattern.prototype.ConcretePrototype2@355da254
c2:com.pattern.prototype.ConcretePrototype2@7291c18f
p2.prop2==cc.prop2 is false
原型模式主要适用于以下场景:
1、类初始化消耗资源较多。
2、new产生的一个对象需要非常繁琐的过程(数据准备、访问权限等)
3、构造函数比较复杂。
4、循环体中生产大量对象时。
在Spring中, 原型模式应用得非常广泛。例如scope=prototype,在我们经常用的JSON.parseObject()也是一种原型模式。
原型模式的优缺点
优点:
1、性能优良, Java自带的原型模式是基于内存二进制流的拷贝, 比直接new一个对象性能上提升了许多。
2、可以使用深克隆方式保存对象的状态,使用原型模式将对象复制一份并将其状态保存起来,简化了创建对象的过程,以便在需要的时候使用(例如恢复到历史某一状态),可辅助实现撤销操作。
缺点:
1、需要为每一个类配置一个克隆方法。
2、克隆方法位于类的内部,当对已有类进行改造的时候,需要修改代码,违反了开闭原则。
3、在实现深克隆时需要编写较为复杂的代码,而且当对象之间存在多重嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来会比较麻烦。因此,深拷贝、浅拷贝需要运用得当。
2793

被折叠的 条评论
为什么被折叠?



