从JDK中学习设计模式——原型模式

505 阅读3分钟

这是我参与11月更文挑战的第11天,活动详情查看:2021最后一次更文挑战

概述

原型模式(Prototype Pattern)是通过拷贝原型的方式来创建一个新的指定对象,属于对象创建型模式。

原型模式中的原型实例仅用来指定创建对象的种类,具体原型的创建是通过克隆实现的。通过克隆方法创建的具体原型是全新的对象,因此每一个克隆对象都是相互独立的,它们在内存中的地址并不相同,对具体原型对象的修改不会对原型对象造成任何影响。例如:张三开了一家水壶制造厂,水壶模具就是原型,这个模具只能用来制造水壶,生产出来的水壶就是具体的原型。对水壶进行打磨和喷漆等加工,并不会影响水壶模具这个原型。

结构

原型模式UML.png

  • Prototype(抽象原型类):所有具体原型类的公共父类,可以是抽象类和接口,也可以是具体的实现类。
  • ConcretePrototype(具体原型类):它实现了具体的克隆方法,在克隆方法中返回自己的一个克隆对象。
  • Client(客户端):让一个原型对象克隆自身从而创建一个新的对象,在客户类中只需要直接实例化或通过工厂方法等方式创建一个原型对象,再通过调用该对象的克隆方法即可得到多个相同的对象。原型类实现了依赖倒置原则,因此客户端可以根据需要选择具体原型类,系统有较好的可扩展性,增加或更换具体原型类都很方便,符合开闭原则

优点

  1. 性能优良,原型模式的拷贝是内存二进制流的拷贝,比直接实例化一个对象的性能高。
  2. 简化对象的创建过程,当创建新对象的实例较为复杂时,通过克隆一个已有的实例就可以了。
  3. 不会受到构造函数的约束,具体原型的创建是通过拷贝实现的,不会执行构造函数。
  4. 扩展性较好,在原型模式中提供了抽象原型类,客户端可以针对抽象原型类进行编程,而将具体原型类写在配置文件中,增加或减少产品类对原有系统都没有任何影响,符合开闭原则

缺点

需要为每个类配备一个克隆方法,当需要对已有的类进行改造时,需要修改源代码,违背了开闭原则

应用场景

  1. 资源或性能优化场景:原型的创建成本较大,如:长时间占用系统资源等,此时就可以通过克隆来减少资源的使用。
  2. 需要保存对象的状态:需要恢复对象的状态到某一刻,如:撤销操作。

JDK 中的应用

java.lang.Object 中使用到了原型模式。

java.lang.Object 是抽象原型:

public class Object {

    protected native Object clone() throws CloneNotSupportedException;
    
}

java.util.ArrayList 等属于具体原型:

public class ArrayList<E> {
    
    public Object clone() {
        try {
            ArrayList<?> v = (ArrayList<?>) super.clone();
            v.elementData = Arrays.copyOf(elementData, size);
            v.modCount = 0;
            return v;
        } catch (CloneNotSupportedException e) {
            throw new InternalError(e);
        }
    }
}