设计模式之原型模式(创建者模式)

65 阅读2分钟

提出问题

  • 现有一个问题,学校要给学生发放十个三好学生的奖状.
  • 解决方案
public class Awards {
   private String name;

   public String getName() {
       return name;
   }

   public void setName(String name) {
       this.name = name;
   }
}
public static void main(String[] args) {
    for (int i = 0; i < 10; i++) {
        Awards awards = new Awards();
        awards.setName("张三"+i+1);
    }

}
  • 执行 main 方法可以得到结果,但是这样也太麻烦了,需要重复的创建十次对象,对于性能该是有一些影响的.

解决问题

  • 对于上面的问题,现在有一个解决的方法,那就是使用原型模式来解决.

原型模式的概念

  • 使用原型实例创建对象,通过克隆原型创建新的对象.
public class Awards implements Cloneable{


   private String name;

   public String getName() {
       return name;
   }

   public void setName(String name) {
       this.name = name;
   }
   @Override
   public Object clone() throws CloneNotSupportedException {
       return super.clone();
   }
}
public static void main(String[] args) throws CloneNotSupportedException {
    Awards awards = new Awards();
    for (int i = 0; i < 10; i++) {
        Awards clone = (Awards) awards.clone();
        clone.setName("张三"+i +1);
    }
}

使用了原型模式必须要让原型对象实现 cloneable 接口,并且重写他的 clone 方法来实现克隆.

原型模式实现的原理

原型模式的克隆实现就是依赖了java 的浅克隆

优点

  • 性能比直接new实现对象要好,适用于对性能和安全要求高的场景
  • 逃避构造函数的约束,优缺点共存的这特点,因为是直接在内存中克隆的,构造函数不会执行

浅克隆

  • 数据类型是基本数据类型的成员变量,浅克隆直接进行值传递,将该属性值直接复制一份给新对象
  • 对于数据类型是引用数据类型的成员变量,如对象,数组...,浅克隆会进行引用传递,会该成员变量的内存地址值复制给新对象,因为两个对象都指向了同一块内存地址,所以无论那个对象的成员变量修改都会影响到其他的对象
  • 注意: 浅克隆中 String 类型同基本数据类型一样

深克隆

  • 会复制对象的所有基本数据类型的成员变量值
  • 会为引用数据类型的成员变量申请新的内存地址,并复制每个引用数据类型变量所引用的对象 对象的深克隆会对整个对象进行克隆

深克隆的实现方式

  • 重写 clone 方法,手动的将引用数据类型克隆一份
  • 使用对象序列化的方式,但是原型对象以及引用数据类型的对象都需要实现 Serializable 接口