原型模式就是通过一个原有的原型对象来表明要创建对象的类型,然后通过复制这个原型对象来创建同类型的对象。
当我们在写一个应用的时候,假如有一个对象,并且这个对象包含了一些有效值,而我们需要和该对象完全相同的新对象来做其他操作,这时我们就可以使用Prototype模式了,通过复制原有的对象,然后在复制后的对象上进行所需操作。
我们要想实现原型模式,可以通过实现java的Cloneable接口,并复写他的clone()方法:
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
Clone分为深度Clone和浅度Clone,如果我们克隆的对象中没有重载了clone()方法的引用类型,那么我们可以使用浅度克隆,如果有并且希望克隆对象中的引用类型也被克隆,那么我们就需要用到深度克隆了,接下来我们看一个例子:
我们有一个Dog类,他有一个legCount变量来表示腿的数量,还有一个DogClone类,来表示Dog的克隆类,并实现了Cloneable接口,复写了clone方法:
Dog类:
package com.dxy.design.pattern.prototype;
public class Dog {
private int legCount;
public Dog(int legCount) {
this.legCount = legCount;
}
public void changeLegCount() {
this.legCount *= 2;
}
@Override
public String toString() {
return Integer.toString(this.legCount);
}
}
DogClone类:
package com.dxy.design.pattern.prototype;
public class DogClone implements Cloneable {
private int legCount;
private Dog dog = new Dog(4);
@Override
protected Object clone() throws CloneNotSupportedException {
DogClone d = (DogClone)super.clone();
return d;
}
public int getLegCount() {
return legCount;
}
public void setLegCount(int legCount) {
this.legCount = legCount;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
}
客户端类Client:
package com.dxy.design.pattern.prototype;
public class Client {
public static void main(String[] args) throws Exception {
DogClone dogClone = new DogClone();
dogClone.setLegCount(3);
System.out.println("原克隆腿数量:"+dogClone.getLegCount());
System.out.println("原腿数量:"+dogClone.getDog());
DogClone dogClone1 = (DogClone)dogClone.clone();
dogClone1.setLegCount(2);
Dog dog = dogClone1.getDog();
dog.changeLegCount();
System.out.println("原克隆腿数量:"+dogClone.getLegCount());
System.out.println("原腿数量:"+dogClone.getDog());
System.out.println("克隆后克隆腿数量:"+dogClone1.getLegCount());
System.out.println("克隆后腿数量:"+dogClone1.getDog());
}
}
执行结果如图:
由执行结果我们可以看出,克隆后的Dog的legCount改变了,而我们需要的是对克隆对象进行操作对原对象无任何影响,这时我们就需要用到深度克隆了,深度克隆需要将克隆类中的引用类型进行克隆,所以Dog类也需要实现Cloneable接口并复写clone()方法:
package com.dxy.design.pattern.prototype;
public class Dog implements Cloneable {
private int legCount;
public Dog(int legCount) {
this.legCount = legCount;
}
public void changeLegCount() {
this.legCount *= 2;
}
@Override
public String toString() {
return Integer.toString(this.legCount);
}
@Override
protected Object clone() throws CloneNotSupportedException {
Dog d = (Dog)super.clone();
return d;
}
}
然后在DogClone类的clone方法里加上:
d.dog = (Dog)dog.clone();
DogClone类:
package com.dxy.design.pattern.prototype;
public class DogClone implements Cloneable {
private int legCount;
private Dog dog = new Dog(4);
@Override
protected Object clone() throws CloneNotSupportedException {
DogClone d = (DogClone)super.clone();
d.dog = (Dog)dog.clone();
return d;
}
public int getLegCount() {
return legCount;
}
public void setLegCount(int legCount) {
this.legCount = legCount;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
}
运行客户端结果如图:
原克隆对象DogClone中的Dog的legCount没有改变,克隆成功。
注意:并不是所有的类都能够实现深度克隆,例如StringBuffer,它没有重载clone()方法,所以它不能实现深度克隆。