Prototype - 原型设计模式

11 阅读2分钟

什么是原型模式?

原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式之一。这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。Java 中的 Object 类实现了 Cloneable,正是对这种设计模式的应用。

优缺点

优点:

1.性能提高。

2.逃避构造函数的约束。

缺点:

1.配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类不是很难,但对于已有的类不一定很容易,特别当一个类引用不支持串行化的间接对象,或者引用含有循环结构的时候。

2.必须实现 Cloneable 接口。

示例

作为一个坦克世界老玩家,提到原型,无法控制的想到虎式原型车。先创建一个 Tiger 类,一个 String 的车组编号,一个List 的车组成员信息。实现 Cloneable 接口并覆写 clone 接口。注意,如果不声明实现接口的话会报 CloneNotSupportedException 异常。

    ```
class Tiger implements Cloneable {
    private String number;
    private List<String> members;

    public void setNumber(String number) {
        this.number = number;
    }

    public String getNumber() {
        return this.number;
    }

    public void setMembers(List<String> members) {
        this.members = members;
    }

    public List<String> getMembers() {
        return this.members;
    }

    @Override
    public Tiger clone() {
        try {
            return (Tiger) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;
    }
}

我们再写一个测试类:

public static void main(String[] args) {
    final Tiger tigerPrototype = new Tiger();
    tigerPrototype.setNumber("001");
    tigerPrototype.setMembers(List.of("Michael Wittmann", "Adelbert Schulz"));
    final Tiger clonedTiger = tigerPrototype.clone();

    System.out.println("tiger prototype number: " + tigerPrototype.getNumber());
    System.out.println("Cloned tiger number: " + clonedTiger.getNumber());
    System.out.println("Cloned object's reference addresses are same? " + (tigerPrototype == clonedTiger));
    System.out.println("member's reference addresses are same? " + (tigerPrototype.getMembers() == clonedTiger.getMembers()));
}

Output:

tiger prototype number: 001 
Cloned tiger number: 001 
member's reference addresses are same? true 
Cloned object's reference addresses are same? false

从输出结果我们可以看出,克隆出的对象和原型对象具有相同的属性值,但对象的内存地址是不同的,但其成员属性如果是引用数据类型,其引用是相同的,因此,如果原型对象中的 Member List 中有修改,其修改结果会反映到所有被克隆出的对象。这种克隆被称为“浅拷贝(Shallow Copy) ”,如果其所有成员属性也是值拷贝,享有独立的内存地址,即称为“深拷贝(Deep Copy) ”。深拷贝一般需要通过 I/O,序列化的途径。可以考虑使用 Apache Commons Lang 或 Gson 等工具来序列化。