这个模式是一个创建型模式,用途至少在我工作中实在排不上用场。所以存在感不是很高

定义

用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

它的核心是clone方法,通过该方法进行对象的拷贝,Java中提供了Cloneable接口帮助我们标识这个对象是可拷贝的。

类图

原型模式类图
原型模式类图

优缺点

优点

性能优良

原型模式是在内存二进制流的拷贝,要比直接new一个对象性能好很多,特别是要在一个循环体内产生大量的对象时,原型模式可以更好地体现其优点。

逃避构造函数的约束

这既是它的优点也是缺点,直接在内存中拷贝,构造函数是不会执行的。优点就是减少了约束,缺点也是减少了约束,需要大家在实际应用时考虑。

应用

资源优化场景

类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。

性能和安全要求的场景

通过new产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式。

一个对象多个修改者的场景

一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。

在实际项目中,原型模式很少单独出现,一般是和工厂方法模式一起出现,通过clone的方法创建一个对象,然后由工厂方法提供给调用者。原型模式已经与Java融为一体,大家可以随手拿来使用。

实现

实现其实很简单,实现Cloneable接口复写clone方法即可!

public class PrototypeObj implements Cloneable {

   //覆写父类Object方法
   @Override
   public PrototypeObj clone() {
      PrototypeObj prototypeObj = null;
      try {
         prototypeObj = (PrototypeObj) super.clone();
      } catch (CloneNotSupportedException e) {
         //异常处理
      }
      return prototypeObj;
   }

}
public class Client {
   public static void main(String[] args) {

      PrototypeObj thing = new PrototypeObj();

      //拷贝一个对象
      PrototypeObj cloneThing = thing.clone();

   }
}

原型模式的注意事项:

深拷贝与浅拷贝

Object类提供的方法clone只是拷贝本对象,其对象内部的数组、引用对象等都不拷贝,还是指向原生对象的内部元素地址,这种拷贝就叫做浅拷贝。内部的数组和引用对象不拷贝,其他的原始类型比如int、long、char等都会被拷贝,但是对于String类型,Java就希望你把它认为是基本类型,它是没有clone方法的,处理机制也比较特殊,通过字符串池(stringpool)在需要的时候才在内存中创建新的字符串,读者在使用的时候就把String当做基本类使用即可。

构造函数不会被执行

一个实现了Cloneable并重写了clone方法的类A,有一个无参构造或有参构造B,通过new关键字产生了一个对象S,再然后通过S.clone()方式产生了一个新的对象T,那么在对象拷贝时构造函数B是不会被执行的。

clone与final互斥

对象的clone与对象内的final关键字是有冲突的,因为final本身作用就是初始化后不可改。所以这两个是互斥的。