Java设计模式——原型模式
原型模式
定义
使用原型实例指定待创建对象的类型,并且通过复制这个原型来创建新的对象。
结构
Prototype(抽象原型类):它是声明克隆方法的接口,是所有具体原型类的公共父类。
ConcretePrototype(具体原型类):它实现在抽象原型类中声明的克隆方法,在克隆方法中返回自己的一个克隆对象。
Client(客户类):在客户类中,让一个原型对象克隆自身,从而创建一个新的对象。
分类
浅克隆
如果原型对象的成员变量是值类型,将复制一份给克隆对象;如果原型对象的成员变量是引用类型,只要将引用对象的地址复制一份克隆对象,也就是说原型对象和克隆对象的成员变量指向相同的内存地址。
深克隆
无论原型对象的成员变量是值类型还是引用类型,都将复制一份给克隆对象,深克隆将原型对象的所有引用对象也复制一份给克隆对象。
类图
原型模式的实现
通过实现方法
在具体原型类的克隆方法中实例化一个与自身类型相同的对象并将其返回,同时将相关的参数传入新创建对象中,保证它们的成员变量相同。
Java语言中的clone()方法和Cloneable接口
在Java中可以直接使用Object提供的**clone()**方法来实现对象的浅克隆。能够实现克隆的Java类必须实现一个标识接口(Cloneable),表示这个Java类支持被复制。如果没有实现,调用clone方法将抛出异常。
Java语言中的clone()方法满足以下几点:
- 对任何对象x,都有x.clone()! = x ,即被克隆对象与原型对象不是同一个对象。
- 对任何对象x,都有x.clone().getClass() ==x.getClass(),即克隆对象应与原型对象的类型一样。
- 如果对象的x的equals()方法定义恰当,那么x.clone().equals(x)应该成立。
直接利用Object类的clone()方法的具体步骤
-
在派生类中覆盖基类(Object类)的clone()方法,并声明为public。
-
在派生类的clone()方法中调用super.clone()。
-
派生类需要实现Cloneable接口。
此时,Object类相当于抽象原型类,所有实现了Cloneable接口的类相当于具体原型类。
优点
- 当创建新的对象较为复杂时,使用原型对象可以简化对象的创建过程,通过复制一个已有实例,可以提高新实例的创建效率。
- 扩展性较好,由于在原型模式中提供了抽象原型类
- 提供了简化的创建结构。
- 可以使用深克隆的方式保存对象的状态。可以辅助实现撤销操作。
缺点
- 需要为每一个类配备一个克隆方法,而且克隆方法位于一个类的内部,当对已有的类进行改造时需要修改源代码,违背了开闭原则。
- 在实现深克隆时需要编写较为复杂的代码。而且当对象之间存在多重的嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来可能会比较麻烦。
适用环境
- 创建新对象成本比较大,新的对象可以通过复制已有对象来获得;如果是相似对象,则可以对其成员变量稍作修改。
- 系统要保存对象的状态,而对象的状态变化很小。
- 需要避免使用多层次对的工厂类来创建分层次的对象,并且类的实例对象只有一个或很少的几个组合状态,通过复制原型对象得到新实例可能比使用构造函数创建一个新实例更加方便。