原型模式 prototype

来源:互联网 发布:青岛网络游戏软件开发 编辑:程序博客网 时间:2024/06/07 09:32

       在创建模式中我们已经讨论了,单例、简单工厂、抽象工厂、构建模式、现在来交流下原型模式,首先原型模式在《Java核心技术》卷中提到,标准库中只有不到5%的类实现了clone( )

       然后使用该类的场景主要在一个类的初始化比较耗费资源,或者说比较费时的情况下。我希望快速得到一个新的该类的对象。为什么用原型模式就快了?因为Object类的clone( )方法的原理是从内存中以二进制流的方式进行拷贝,重新分配一个内存块,那样构造函数也不会执行。

       在实际项目中,原型模式很少单独出现,一般是和工厂方法模式一起出现,通过clone( )的方法创建一个对象,然后由工厂方法提供给调用者。

       JAVA的深拷贝浅拷贝问题,基本数据类型都是深拷贝,数组及对象都是浅拷贝,在对String进行处理是,把它当做基本数据类型来处理就可以了。

       final关键字修饰的对象,不能进行深拷贝。

Java实现原型模式代码

package com.prototype;import java.awt.List;import java.util.Date;public class Prototype implements Cloneable {//基本类型,jvm执行深拷贝;private int anInt = 0;//引用类型,拷贝引用,jvm执行浅拷贝;private String str = new String("prototype");//引用类型,拷贝引用,jvm执行浅拷贝;private Date date = new Date();private final List list = new List();@Overridepublic Object clone() throws CloneNotSupportedException {Prototype clone = (Prototype) super.clone();//final修饰的变量不能对引用进行修改//list = new List();这句话编译不过;//对于引用变量,在进行克隆的时候,jvm只会简单的拷贝引用值,//如果需要实现引用的对象不一样就需要生成新的对象,并赋给引用变量。//在这里String引用也是引用变量,但是其实是没有必要生成 新的String对象,为什么呢?//因为,String是一个不可变类,初始化后该对象就不会改变了,所以多个引用变量指向同一个对象就没有数据不一致的可能性了clone.date = new Date();return clone;}}

这里有几个问题:

为什么必须实现Cloneable接口,这个接口里面没有方法,我们实现的clone( )是覆盖的Object对象的方法?

其实这里就是标记接口(marker interface),表示该对象是否可以被克隆,在选择方法的时候,最后选择了通过继承来实现。在知乎上有关于这个问题的讨论,链接。


String这个引用数据类型,为什么在处理的时候把其视为基本数据类型来使用?

这里的原因就在于String的是一个不可变类(对于不可变类,这里看过来~!),所以一旦初始化后,对像内部的属性就不会改变了。所以也就没必要生成新的String对象赋值给String引用进行深拷贝了。


数组的clone()实现是由虚拟机内部实现的,实现为每个数组均包含一个clone()方法,是public的。可以利用这个方法创建一个包含所有数据元素拷贝的新数组。