什么是原型模式:
原型模式属于对象的创建模式。通过给出一个原型对象来指明所有创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象。
说白了,就是对象的克隆。克隆又分为浅克隆和深克隆。
浅克隆:只负责克隆按值传递的数据(比如基本数据类型、String类型),而不复制它所引用的对象,换言之,所有的对其他对象的引用都仍然指向原来的对象。
深克隆:除了浅度克隆要克隆的值外,还负责克隆引用类型的数据。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深度克隆把要复制的对象所引用的对象都复制了一遍,而这种对被引用到的对象的复制叫做间接复制。
深度克隆要深入到多少层,是一个不易确定的问题。在决定以深度克隆的方式复制一个对象的时候,必须决定对间接复制的对象时采取浅度克隆还是继续采用深度克隆。因此,在采取深度克隆时,需要决定多深才算深。此外,在深度克隆的过程中,很可能会出现循环引用的问题,必须小心处理。
角色:
这种形式涉及到三个角色:
(1)客户(Client)角色:客户类提出创建对象的请求。
(2)抽象原型(Prototype)角色:这是一个抽象角色,通常由一个Java接口或Java抽象类实现。此角色给出所有的具体原型类所需的接口。
(3)具体原型(Concrete Prototype)角色:被复制的对象。此角色需要实现抽象的原型角色所要求的接口。
案例:
1.具体原型:悟空角色和金箍棒
public class Wukong extends Prototype {
private static final long serialVersionUID = 1L;
private float weight;
private int year;
private GoldenCudgel goldenCudgel;
public GoldenCudgel getGoldenCudgel() {
return goldenCudgel;
}
public void setGoldenCudgel(GoldenCudgel goldenCudgel) {
this.goldenCudgel = goldenCudgel;
}
public float getWeight() {
return weight;
}
public void setWeight(float weight) {
this.weight = weight;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
}
public class GoldenCudgel implements Serializable {
private static final long serialVersionUID = 1L;
private float height = 10;
private float wight = 0.1f;
public float getHeight() {
return height;
}
public void setHeight(float height) {
this.height = height;
}
public float getWight() {
return wight;
}
public void setWight(float wight) {
this.wight = wight;
}
}
2. 抽象原型(Prototype)角色
public abstract class Prototype implements Cloneable, Serializable {
private static final long serialVersionUID = 1L;
/**
* 深克隆
*
* @return
* @throws IOException
* @throws ClassNotFoundException
*/
public Object deepClone() throws IOException, ClassNotFoundException {
// 将对象写到流里
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
// 从流里读回来
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
}
/*
* 浅克隆
* @see java.lang.Object#clone()
*/
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
3. 客户(Client)角色,这里直接以测试类作为客户,复制角色
public class MainTest {
public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException {
Wukong wukong1 = new Wukong();
wukong1.setYear(10000);
wukong1.setWeight(100f);
GoldenCudgel goldenCudgel = new GoldenCudgel();
wukong1.setGoldenCudgel(goldenCudgel);
// 浅克隆
Wukong wukong2 = (Wukong) wukong1.clone();
System.out.println("浅克隆后对象是否是一样:" + (wukong1 == wukong2));
System.out.println("浅克隆后,金箍棒是否一样:"
+ (wukong1.getGoldenCudgel() == wukong2.getGoldenCudgel()));
// 深度克隆
Wukong wukong3 = (Wukong) wukong1.deepClone();
System.out.println("深度克隆后对象是否是一样:" + (wukong1 == wukong3));
System.out.println("深度克隆后,金箍棒是否一样:"
+ (wukong1.getGoldenCudgel() == wukong3.getGoldenCudgel()));
}
}