一、概念
原型模式,可以理解为浅复制和深复制。
二、代码示例
/**
* 用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象。
*/
public class Prototype implements Cloneable {
// 这是浅拷贝
public Object clone() throws CloneNotSupportedException {
// 这个clone方法重写的是基类Object中的方法,所以通过super.clone()就可以指向它的内存引用复制出一个新的对象。即调用super.clone() 得到的是当前调用类的副本,而不是父类的副本。
// 实现Cloneable接口重写Clone方法后,在这个clone方法体中如果调用this.clone()就是调用自身的这个方法,陷入递归调用中从而形成死循环抛异常。
return super.clone();
}
}
public class ConcretePrototype implements Cloneable {
private int age;
private String name;
// 这里必须用ArrayList而不能用List
public ArrayList arrayList;
// 这是浅拷贝
public Object clone() throws CloneNotSupportedException {
// 这个clone方法重写的是基类Object中的方法,所以通过super.clone()就可以指向它的内存引用复制出一个新的对象。即调用super.clone() 得到的是当前调用类的副本,而不是父类的副本。
// 实现Cloneable接口重写Clone方法后,在这个clone方法体中如果调用this.clone()就是调用自身的这个方法,陷入递归调用中从而形成死循环抛异常。
return super.clone();
}
// 这是深拷贝
public Object deepClone() throws CloneNotSupportedException {
ConcretePrototype prototype = (ConcretePrototype) super.clone();
prototype.arrayList = (ArrayList) arrayList.clone();
return prototype;
}
public ConcretePrototype(int age, String name, ArrayList arrayList) {
this.age = age;
this.name = name;
this.arrayList = arrayList;
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
public ArrayList getArrayList() {
return arrayList;
}
public void setAge(int age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public void setArrayList(ArrayList arrayList) {
this.arrayList = arrayList;
}
}
/**
* 浅拷贝和深拷贝
* 1.实现Cloneable接口,重写Object的clone()方法并通过super.clone()返回克隆对象。
* 2.如果要拷贝对象存在引用类型,引用对象中也要实现Cloneable接口,并重写clone()方法。
* 3.依赖阿里巴巴的fastJSON包 Account clone = JSONObject.parseObject(JSONObject.toJSONBytes(account), Account.class);
* 4.使用ObjectStream序列化实现深克隆
*/
public class RunMain {
public static void main(String[] args) throws CloneNotSupportedException {
ArrayList arrayList = new ArrayList();
arrayList.add(100);
ConcretePrototype zs = new ConcretePrototype(18, "zs", arrayList);
System.out.println(zs + "{age=" + zs.getAge() + ", name='" + zs.getName() + "\', list=" + zs.getArrayList() + '}');
// 1.复制的引用,两个引用指向同一个对象。当zs的八大基本类型和字符串类型字段改变时,cp也会发生改变。
// ConcretePrototype cp = zs;
// 2.这是浅拷贝。当zs的引用类型字段改变时,cp也会发生改变。其他类型不改变。
ConcretePrototype cp = (ConcretePrototype) zs.clone();
System.out.println(cp + "{age=" + cp.getAge() + ", name='" + cp.getName() + "\', scorelist=" + cp.getArrayList() + '}');
// 3.这是深拷贝。当zs的引用类型字段改变时,cp不会发生改变。其他类型不改变。
ConcretePrototype decp = (ConcretePrototype) zs.deepClone();
System.out.println(decp + "{age=" + decp.getAge() + ", name='" + decp.getName() + "\', scorelist=" + decp.getArrayList() + '}');
}
}