原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
在 Java 中,Object 的 clone() 方法就属于原型模式,不妨简单的理解为:原型模式就是用来克隆对象的。
Java 的赋值只是引用传递,而不是值传递。这样赋值之后,yourMilkTea 仍然指向的周杰伦的奶茶,并不会多一份一样的奶茶。
Java 中有一个语法糖,让我们并不需要手写 clone 方法。这个语法糖就是 Cloneable 接口,我们只要让需要拷贝的类实现此接口即可。
值得注意的是,Java 自带的 clone 方法是浅拷贝的。也就是说调用此对象的 clone 方法,只有基本类型的参数会被拷贝一份,非基本类型的对象不会被拷贝一份,而是继续使用传递引用的方式。如果需要实现深拷贝,必须要自己手动修改 clone 方法才行。
import java.util.*;
/**
* @author Lenovo
*
*/
public class MilkTea implements Cloneable{
public String type;
public boolean ice;
public ArrayList<Integer> list = new ArrayList();
protected MilkTea shallowClone() throws CloneNotSupportedException {
return (MilkTea) super.clone();
}
protected MilkTea deepClone() throws CloneNotSupportedException {
MilkTea deepClone = (MilkTea) super.clone();
deepClone.list = new ArrayList(this.list);
return deepClone;
}
@Override
public String toString() {
return "MilkTea [type=" + type + ", ice=" + ice + ", list=" + list.toString() + "]";
}
public static void main(String[] args) throws CloneNotSupportedException {
MilkTea mt = new MilkTea();
mt.type = "红茶";
mt.ice = false;
mt.list.add(1);
mt.list.add(2);
//MilkTea [type=红茶, ice=false, list=[1, 2]]
System.out.println(mt);
/**浅拷贝*/
MilkTea mtShallowClone = mt.shallowClone();
//MilkTea [type=红茶, ice=false, list=[1, 2]]
System.out.println(mtShallowClone);
mtShallowClone.list.remove(0);
mtShallowClone.ice = true;
//MilkTea [type=红茶, ice=false, list=[2]]
System.out.println(mt);
//MilkTea [type=红茶, ice=true, list=[2]]
System.out.println(mtShallowClone);
/**深拷贝*/
MilkTea mtDeepClone = mt.deepClone();
//MilkTea [type=红茶, ice=false, list=[2]]
System.out.println(mtDeepClone);
mtDeepClone.list.add(777);
//MilkTea [type=红茶, ice=false, list=[2, 777]]
System.out.println(mtDeepClone);
//MilkTea [type=红茶, ice=false, list=[2]]
System.out.println(mt);
}
}