@Catyee
2021-04-04T19:49:18.000000Z
字数 1553
阅读 446
设计模式
原型模式(Prototype Pattern)是指用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象。
1、初始化需要太长时间或者消耗较多资源
2、通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式(构造器的实现过于复杂)
3、同一个类要产生大量相似的对象
原型模式的核心是一个clone方法,通过该方法进行对象的拷贝,只需要实现Cloneable接口并重写clone方法就可以了。这里用一种简单的实现方式作为示例,但是这并不是一个模板,实际开发过程中要灵活处理:
public class Prototype implements Cloneable {
public Prototype clone(){
Prototype prototype = null;
try {
prototype = (Prototype) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return prototype;
}
}
public class ConcretePrototype extends Prototype {
public void show(){
System.out.println("原型模式实现类");
}
}
public class Client {
public static void main(String[] args) {
ConcretePrototype cp = new ConcretePrototype();
for (int i=0; i< 10; i++) {
ConcretePrototype clonecp = (ConcretePrototype) cp.clone();
clonecp.show();
}
}
}
原型模式创建对象比直接new一个对象在性能上要好的多,因为Object类的clone方法是一个本地方法,它直接操作内存中的二进制流,特别是复制大对象时,性能的差别非常明显。同时,由于使用clone方法是操作内存中的二进制流,所以不会执行构造函数。
原型模式虽然很简单,但是在Java中使用clone方法有一些特别需要注意的地方,那就是深浅拷贝问题。
所谓浅拷贝就是只拷贝对象的引用,也就是说并没有基于原有对象创建一个新的对象,只是创建了一个指向原有对象的新的引用,这个时候旧的引用和新的引用都指向这个对象,通过旧引用和新引用操作的都是同一个对象,在并发的时候就可能出现意料之外的情况。
而深拷贝是基于原对象创建一个新的对象,旧的引用指向旧的对象,新的引用指向新的对象。操作的是不同的对象,所以并发的时候也就不会出现问题。
在java中使用clone方法的时候,只有基础类型及基础类型的包装类,然后还有String类型是深拷贝,其它普通对象、数组都只是浅拷贝。其实不光是clone方法,还有Arrays.copyOf()、ArrayList的addAll()方法(底层都是System.arraycopy()方法,这是一个native方法),这些方法都是类似的,拷贝的时候只有基础类型及基础类型的包装类,然后还有String类型是深拷贝,其它普通对象、数组都只是浅拷贝。使用的时候要特别注意。
深拷贝其实有多种实现方式。深拷贝实际上就是创建一个新的对象,这个对象的每个属性都是新的对象,属性的属性也是新的对象。所以一种实现思路就是调用构造方法重新构建(每个属性对象也要重新创建),第二种是每个属性对象都执行clone方法来创建。另外也有一些现成的工具类可以使用,比如Apache Commons Lang包中的SerializationUtils工具类。