JDK设计模式(四)原型模式

用原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象。
在原型模式中,所发动创建的对象通过请求原型对象来拷贝原型对象自己来实现创建过程,当然所发动创建的对象需要知道原型对象的类型。这里也就是说所发动创建的对象只需要知道原型对象的类型就可以获得更多的原型实例对象,至于这些原型对象时如何创建的根本不需要关心,其类图如下所示。
image.png
原型模式主要包含如下三个角色:

  • Prototype:抽象原型类。声明克隆自身的接口。
  • ConcretePrototype:具体原型类。实现克隆的具体操作。
  • Client:客户类。让一个原型克隆自身,从而获得一个新的对象。

讲到原型模式,我们就不得不区分两个概念:深拷贝、浅拷贝。

  • 浅拷贝:使用一个已知实例对新创建实例的成员变量逐个赋值,这个方式被称为浅拷贝。
  • 深拷贝:当一个类的拷贝构造方法,不仅要复制对象的所有非引用成员变量值,还要为引用类型的成员变量创建新的实例,并且初始化为形式参数实例值。

JDK 中使用的原型模式

image.png
所有的 Java 类都继承至 Object,而 Object 类提供了一个 clone()方法,该方法可以将一个 java 对象复制一份,因此在 java 中可以直接使用 clone()方法来复制一个对象。但是需要实现 clone 的 Java 类必须要实现一个接口:Cloneable.该接口表示该类能够复制且具体复制的能力,如果不实现该接口而直接调用 clone()方法会抛出 CloneNotSupportedException 异常。

public class ObjectClone implements Cloneable{
    public Object clone(){
        Object object = null;
        try {
                object = super.clone();
        } catch (CloneNotSupportedException exception) {
                System.err.println("Not support cloneable");
        }
        return object;
    }
}

Java 中任何实现了 Cloneable 接口的类都可以通过调用 clone()方法来复制一份自身然后传给调用者。一般而言,clone()方法满足:
1)对任何的对象 x,都有 x.clone() !=x,即克隆对象与原对象不是同一个对象。
2)对任何的对象 x,都有 x.clone().getClass()==x.getClass(),即克隆对象与原对象的类型一样。
3)如果对象 x 的 equals()方法定义恰当,那么 x.clone().equals(x)应该成立。

原型模式优点

1、如果创建新的对象比较复杂时,可以利用原型模式简化对象的创建过程,同时也能够提高效率。
2、可以使用深克隆保持对象的状态。
3、原型模式提供了简化的创建结构。

原型模式缺点

1、在实现深克隆的时候可能需要比较复杂的代码。
2、需要为每一个类配备一个克隆方法,而且这个克隆方法需要对类的功能进行通盘考虑,这对全新的类来说不是很难,但对已有的类进行改造时,不一定是件容易的事,必须修改其源代码,违背了“开闭原则”。

使用场景

1、如果创建新对象成本较大,我们可以利用已有的对象进行复制来获得。
2、如果系统要保存对象的状态,而对象的状态变化很小,或者对象本身占内存不大的时候,也可以使用原型模式配合备忘录模式来应用。相反,如果对象的状态变化很大,或者对象占用的内存很大,那么采用状态模式会比原型模式更好。
3、需要避免使用分层次的工厂类来创建分层次的对象,并且类的实例对象只有一个或很少的几个组合状态,通过复制原型对象得到新实例可能比使用构造函数创建一个新实例更加方便。

总结

1、原型模式向客户隐藏了创建对象的复杂性。客户只需要知道要创建对象的类型,然后通过请求就可以获得和该对象一模一样的新对象,无须知道具体的创建过程。
2、克隆分为浅克隆和深克隆两种。
3、我们虽然可以利用原型模式来获得一个新对象,但有时对象的复制可能会相当的复杂,比如深克隆。

https://alicharles.oss-cn-hangzhou.aliyuncs.com/static/images/mp_qrcode.jpg
文章目录
  1. JDK 中使用的原型模式
  2. 原型模式优点
  3. 原型模式缺点
  4. 使用场景
  5. 总结