原型模式(Prototype)

来源:互联网 发布:短信轰炸软件免费版 编辑:程序博客网 时间:2024/06/05 09:43

原型模式

概念

原型模式(Prototype)属于创建型模式,它通过复制一个已经存在的实例来返回新的实例,而不是新建实例,被复制的实例就是我们所称的原型,这个原型是可定制的。

原型模式多用于创建复杂的或者耗时的实例,因为这种情况下,复制一个已经存在的实例可以使程序运行更加高效,或者创建值相等,只是命名不一样的同类数据。

类图

原型模式

示例

public class Prototype implements Cloneable {      @Override    public Object clone() {        Prototype prototype = null;          try{            prototype = (Prototype)super.clone();          }catch(CloneNotSupportedException e){              e.printStackTrace();          }        return prototype;       }}public class ConcretePrototype extends Prototype{      public void print(){          System.out.println("ConcretePrototype");      }  }  public class Client {      public static void main(String[] args){          ConcretePrototype cp = new ConcretePrototype();          for(int i=0; i< 10; i++){              ConcretePrototype clonePrototype = (ConcretePrototype)cp.clone();              clonePrototype.print();          }      }  } 

优点

  • 简化对象的创建,只需要调用一个clone方法即可。
  • 原型模式创建对象比使用new关键字创建对象性能好很多,因为Object类的clone方法是一个本地方法,它直接操作内存中的二进制流,特别是复制大对象时,性能的差别非常明显。

适用对象

  • 在需要重复地创建相似对象时可以考虑使用原型模式,比如在一个循环体内创建对象。
  • 如果对象创建比较复杂或者重复创建次数很多,使用clone方法可以提高性能

注意事项

  • 使用原型模式复制对象不会调用类的构造方法。因为对象的复制是通过调用Object类的clone方法来完成的,它直接在内存中复制数据,因此不会调用类的构造方法。
  • 访问权限对原型模式无效,这里是因为,在浅拷贝时,如果成员变量是对象,则只拷贝对象引用,即新拷贝出的对象与原有对象共享该实例变量,不受访问权限的限制。这在Java中很疯狂,因为它突破了访问权限的定义,一个private修饰的变量,竟然可以被两个实例对象访问。
  • 深拷贝与浅拷贝。Object类的clone方法只会拷贝对象中的基本数据类型及其他的类型(java中的8种基本类型以及它们的封装类型,String类型),对于数组,容器对象,引用对象等都不会拷贝,这就是浅拷贝。如果要实现深拷贝,必须将原型模式中的数组、容器对象、引用对象另行拷贝。

“浅拷贝”和“深拷贝”

  • 浅拷贝:对值类型的成员变量进行值的复制,对引用类型的成员变量只复制引用,不复制引用的对象。
  • 深拷贝:对值类型的成员变量进行值的复制,对引用类型的成员变量也进行引用对象的复制。
    浅拷贝的规则:
    1、基本类型
    如果变量是基本类型,则拷贝其值,比如:int、float、long等。
    2、String字符串
    拷贝的是地址,是个引用,两个String对象的地址是相同的,但是在修改的时候,它会从字符串池(String Pool)中重新生成新的字符串,原有的字符串对象保持不变,但是。
    3、对象
    如果变量是一个实例对象,则拷贝地址引用,也就是说此时新拷贝出的对象与原有对象共享该实例变量,不受访问权限的限制。

深拷贝的规则:
1、基本类型
如果变量是基本类型,则拷贝其值,比如:int、float、long等。
2、String字符串
String类是final类型的,并且并未重写clone方法,所以无法调用String.clone方法实现所谓的深拷贝,不过,String类尽管只是拷贝的引用,即地址,但是修改时会从String Pool中重新生成字符串,而原有的字符串对象保持不变,类似于深拷贝
3、对象
如果变量是一个实例对象,则调用该对象的clone方法实现拷贝,该对象必须也实现了Cloneable接口,否则会抛异常

深拷贝代码如下:

public class Prototype implements Cloneable {      private ArrayList list = new ArrayList();      @Override    public Object clone(){          Prototype prototype = null;          try{              prototype = (Prototype)super.clone();              prototype.list = (ArrayList) this.list.clone();          }catch(CloneNotSupportedException e){              e.printStackTrace();          }          return prototype;       }  }  

参考

23种设计模式(5):原型模式
Java中的Cloneable接口与深拷贝、浅拷贝

原创粉丝点击