创建型设计模式之原型模式

84 阅读2分钟

1. 原型模式

原型模式(Prototype Pattern)定义:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

不通过 new 关键字来产生一个对象,而是通过对象复制来实现的模式就叫做原型模式。

原型模式的核心是一个 clone 方法,通过该方法进行对象的拷贝,Java 提供了一个 Cloneable 接口来标识这个对象是可拷贝的。所以实现一个 Cloneable 接口,再重写一下 Object 类下的 clone 方法,就完成了原型模式。

public class PrototypeClass implements Cloneable{
    @Override
    protected PrototypeClass clone() {
        PrototypeClass prototypeClass = null;
        try {
            prototypeClass = (PrototypeClass) super.clone();
        } catch (CloneNotSupportedException e) {
            //异常处理
        }
        return prototypeClass;
    }
}

2. 原型模式的应用

原型模式是在内存二进制流的拷贝,要比直接 new 一个对象性能好很多。直接在堆内存中拷贝,构造函数是不会执行的。

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

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

浅拷贝和深拷贝

Object 类提供的 clone 方法只拷贝本对象,对象内部的数组,引用对象等都非基本数据类型的成员变量不拷贝,还是指向原生对象的内部元素地址,这就是浅拷贝。

如果对象内部成员变量是 String 类型的话,String 存在于堆内存、常量池;比较特殊,String 本身没有实现 Cloneable 接口,传递是引用地址;由于 String 本身的 final 性,每次赋值都是一个新的引用地址,原对象的引用和副本的引用互不影响。因此 String 就和基本数据类型一样,表现出了"深拷贝"特性。

Object 的 clone() 方法,在深拷贝的时候,不适用于有对象多层嵌套的情况(每一层都得进行拷贝,很麻烦)。所以深拷贝还有一种实现方法,就是通过二进制流来操作对象,实现拷贝。这样就不需要递归让所有嵌套对象实现 Cloneable 接口,只需要让被拷贝对象实现 Serializable 接口即可。

深拷贝和浅拷贝建议不要混合使用,特别是在涉及到类的继承时,父类有多个引用的情况下就非常复杂。

要使用 clone() 方法,类的成员变量上不要加 final 关键字。