原型模式(Prototype)
定义
用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
UML结构图
浅复制
ProtoType
package com.csdhsm.pattemdesign.prototype; import java.util.ArrayList; import java.util.List; /** * @Title: Prototype.java * @Description: 浅复制 * @author: Han * @date: 2016年6月21日 下午9:09:28 */ public class Prototype implements Cloneable { private String name; private List<String> list = new ArrayList<>(); public String getName() { return name; } public void setName(String name) { this.name = name; } public void add(String str) { this.list.add(str); } public List<String> getList() { return list; } public void setList(List<String> list) { this.list = list; } //克隆方法返回对象 @Override protected Object clone() { try { return super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); return null; } } }
客户端
package com.csdhsm.pattemdesign.prototype; public class Solution { public static void main(String[] args) { Prototype pro = new Prototype(); pro.setName("original object"); pro.add("original object1"); Prototype pro1 = (Prototype) pro.clone(); pro1.setName("changed object1"); pro1.add("original object2"); System.out.println("original object:" + pro.getName()); System.out.println("cloned object:" + pro1.getName()); System.out.println("original object:" + pro.getList()); System.out.println("cloned object:" + pro1.getList()); } }
结果
问题分析
在基本数据类型(int,double,float...)和String对象时,这种复制是没有什么问题的,因为浅复制只对值进行复制,如果是引用类型变量(例如List,Person...)时,只会复制引用,也就是说,在内存里,复制前和复制后在内存里是指向同一个实例,所以在上个例子中,对于List对象,复制后生成的对象添加数据,会引起原对象的变化,这就是所谓的深复制和浅复制的区别。
深复制
ProtoType
package com.csdhsm.pattemdesign.prototype; import java.util.ArrayList; /** * @Title: Prototype.java * @Description: 深复制 * @author: Han * @date: 2016年6月21日 下午9:09:28 */ public class Prototype implements Cloneable { private String name; private ArrayList<String> list = new ArrayList<>(); public String getName() { return name; } public void setName(String name) { this.name = name; } public void add(String str) { this.list.add(str); } public ArrayList<String> getList() { return list; } public void setList(ArrayList<String> list) { this.list = list; } //克隆方法返回对象 @SuppressWarnings("unchecked") @Override protected Object clone() { Prototype pro2 = null; try { pro2 = (Prototype) super.clone(); //深复制重点在这句代码,重新新生成一个对象,赋给新对象的list pro2.setList((ArrayList<String>) this.list.clone()); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return pro2; } }
客户端代码不变
结果
OK,深复制成功!