原型(Prototype)模式的定义如下:用一个已经创建的实例作为原型,通过复制该原型对象来创建一个和原型相同或相似的新对象。
原型模式的优点:
- Java自带的原型模式基于内存二进制流的复制,在性能上比直接 new 一个对象更加优良。
- 可以使用深克隆方式保存对象的状态,使用原型模式将对象复制一份,并将其状态保存起来。
原型模式的缺点
- 需要为每一个类都配置一个 clone 方法
- 当实现深克隆时,需要编写较为复杂的代码,而且当对象之间存在多重嵌套引用时,为了实现深克隆,每一层对象对应的类都必须支持深克隆,实现起来会比较麻烦。
原型模式的结构如下所示:
原型模式的克隆分为浅克隆和深克隆。
浅克隆:浅克隆仅仅复制所考虑的对象,不会复制它所引用的成员对象。
深克隆:对象本身被复制外,对象包含的引用也被复制,也就是其中的成员对象也被复制。
Java 中的 Object 类提供了浅克隆的 clone() 方法,具体原型类只要实现 Cloneable 接口就可实现对象的浅克隆,这里的 Cloneable 接口就是抽象原型类。其代码如下:
// 具体原型类 public class RealizeType implements Cloneable { public RealizeType() { System.out.println("具体原型创建成功!"); } public Object clone() throws CloneNotSupportedException { System.out.println("具体原型复制成功!"); return super.clone(); } } // 原型模式测试类 public class Main { public static void main(String[] args) throws CloneNotSupportedException { RealizeType object1 = new RealizeType(); RealizeType object2 = (RealizeType) object1.clone(); boolean isEquals = object1 == object2 ? true : false; System.out.println(isEquals); } }
我们针对上述的实例进行修改成深克隆的案例。
在Attribute重写clone()方法,并声明为public
在Attribute的clone方法中,调用super.clone()
在Attribute中实现Cloneable接口
示例代码如下所示:
// Attribute public class Attribute implements Cloneable{ private String name; public Attribute(String name) { this.name = name; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } public String getName() { return name; } public void setName(String name) { this.name = name; } } // 原型类 public class RealizeType implements Cloneable { private Attribute attribute; public RealizeType() { System.out.println("具体原型创建成功!"); } public Object clone() throws CloneNotSupportedException { System.out.println("具体原型复制成功!"); RealizeType realizeType = (RealizeType) super.clone(); realizeType.attribute = (Attribute) realizeType.attribute.clone(); return realizeType; } public Attribute getAttribute() { return attribute; } public void setAttribute(Attribute attribute) { this.attribute = attribute; } } // 测试类 public class Main { public static void main(String[] args) throws CloneNotSupportedException { Attribute attribute1 = new Attribute("属性1"); RealizeType object1 = new RealizeType(); object1.setAttribute(attribute1); Attribute attribute2 = new Attribute("属性2"); RealizeType object2 = (RealizeType) object1.clone(); object2.setAttribute(attribute2); System.out.println("RealizeType1:" + object1.getAttribute().getName()); System.out.println("RealizeType2:" + object2.getAttribute().getName()); } }
输出结果如下:
具体原型创建成功! 具体原型复制成功! RealizeType1:属性1 RealizeType2:属性2
注意:在原型模式中,如果拷贝的类中含有引用成员变量则需要使用深拷贝的方式。