【设计模式】- 原型模式

简介

原型模式属于创建型模式,通过拷贝原型来创建新的对象。原型模式多用于创建复杂的或者构造耗时的实例,因为复制一个已经存在的实例可以提高程序的运行效率。

场景

  1. 类初始化需要消耗很多的资源。
  2. 通过new创建一个对象,需要繁琐的数据准备或访问权限。
  3. 当被多个调用者使用,但需要保护原型时

注意

通过实现Cloneable接口的原型模式在调用clone函数构造实例时,并不一定比通过new效率更高。只有当new构建对象较为耗时或者成本比较高时,通过clone方法才能够获取效率上的提升。

UML

设计模式 - prototype.png
  • Prototype具备clone功能的原型类

举例

public class Prototype implements Cloneable{

    private String name;
    private ArrayList integers;
    @Override
    protected Object clone() throws CloneNotSupportedException {
        Prototype prototype = (Prototype) super.clone();
        prototype.name = this.name;
        prototype.integers = this.integers;
        return prototype;
    }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public ArrayList getIntegers() { return integers; }
    public void setIntegers(ArrayList integers) { this.integers = integers; }

    public static void main(String[] args) throws IOException {
        Prototype prototype = new Prototype();
        //拷贝
        try {
            Prototype prototypeClone = (Prototype) prototype.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }
}

浅拷贝和深拷贝

说到拷贝,那么就不得不讲一讲浅拷贝和深拷贝。这个只针对于引用类型的数据。浅拷贝只是简单的赋值,并不会创建新的对象。而深拷贝,是返回新创建对象。比如下面有个对象A,里面有个引用类型变量B


对象A.png
  • 浅拷贝


    浅拷贝.png

浅拷贝只是将对象A中变量B(堆中变量B的地址)直接赋值给对象B中的变量B,其实对象A中的变量B和对象B中的变量B都指向堆中同一个对象,那么不管是堆那个进行操作,实在都是在改变堆中的变量B对象。所以对象A改变了变量B,那么对象B拿到的变量B的值就是对象A操作过后的值,反之,也一样。

  • 深拷贝


    深拷贝.png

    深拷贝会重新在堆创建对象,然后把新对象赋值给对象B,这样对象A和对象B操作的就是不同的地址的对象,互不影响。

Java中常用的浅拷贝和深拷贝

  • System.arraycopy(Object src, int srcPos,Object dest, int destPos,int length)
    参数:

    src      the source array.
    srcPos   starting position in the source array.
    dest     the destination array.
    destPos  starting position in the destination data.
    length   the number of array elements to be copied.
    

    写代码测试一下,是深拷贝还是浅拷贝。

    static class PrototypeA{
        public PrototypeA(String name){ this.name = name;}
        public String name;
    }
    public static void main(String[] args) throws IOException {
        PrototypeA[] src = new PrototypeA[2];
        src[0] = new PrototypeA("srcOne");
        src[1] = new PrototypeA("srcTwo");
        //拷贝
        PrototypeA[] des = new PrototypeA[2];
        System.arraycopy(src,0,des,0,src.length);
        des[1].name = "copyTwo";
        //打印
        System.out.println("src:des[0] = " + src[0].name+  "  des[1] = "+src[1].name);
        System.out.println("des:des[0] = " + des[0].name+  "  des[1] = "+des[1].name);
    
    }
    

    打印结果

      src:des[0] = srcOne  des[1] = copyTwo
      des:des[0] = srcOne  des[1] = copyTwo
    

    所以System.arraycopy属于浅拷贝

  • Object.clone()

      static class PrototypeA{
          public PrototypeA(String name){ this.name = name;}
          public String name;
      }
    
      public static void main(String[] args) throws IOException {
          Prototype src = new Prototype();
          src.prototypeA = new PrototypeA("srcOne");
          src.name = "srcOne";
          //拷贝
          try {
              Prototype dest = (Prototype) src.clone();
              dest.prototypeA.name = "copyOne";
              System.out.println("src:name = " + src.prototypeA.name);
              System.out.println("dest:name = " + dest.prototypeA.name);
          } catch (CloneNotSupportedException e) {
              e.printStackTrace();
          }
      }
    

    所以Object.clone()是浅拷贝

扩展

其实可以将原型模式进行聚合或者组合。这样可以在原型上进行方法,属性扩展。而不局限于原型有的方法和属性。

你可能感兴趣的:(【设计模式】- 原型模式)