七、原型模式(深浅克隆)
类似“影之分身术”的东西,以“鸣人”为原型,复制1000份出来,群殴之……
在初始化信息不发生变化的情况下,克隆是最好的办法。既隐藏了对象创建的细节,又对性能大大的提高——不用重新初始化对象,而是动态地获得对象运行时的状态。
——摘自《大话设计模式》
提到原型模式,就不得不提深浅克隆。两者都是完成对原型的复制,而区别在于对其引用对象的复制情况:
浅复制:仅仅复制原型,而对其他对象的引用仍指向原有对象,即不复制原型的引用对象。
深复制:把原型和原型的引用对象都复制了一遍。
一、浅复制
以简历复制为例,进行代码演示
①、原型#########################################
/** *原型,个人简历,实现Cloneable接口 */public class Resume implements Cloneable{private String name;private Integer age;private Character sex;private WorkExperience work; //工作简历的引用//初始化姓名public Resume(String name,WorkExperience work){this.name = name;this.work = work;}//设置个人信息public void setPersonalInfo(Character sex,Integer age){this.sex = sex;this.age = age;}//设计工作经历public void setWorkExperience(String timeArea,String company){work.setTimeArea(timeArea);work.setCompany(company);}public void display(){System.out.println("个人信息:"+name+"\t"+age);System.out.println("工作经历:"+work.getTimeArea()+"\t"+work.getCompany());}@Overridepublic Object clone(){ //浅克隆,直接调用Object的clone方法Object ob = null;try {ob = super.clone();} catch (Exception e) {e.printStackTrace();}return ob;}}
②、原型的引用类#########################################
/** *工作简历 */public class WorkExperience{private String timeArea; //时间段private String company; //所在公司public String getTimeArea() {return timeArea;}public void setTimeArea(String timeArea) {this.timeArea = timeArea;}public String getCompany() {return company;}public void setCompany(String company) {this.company = company;}}
测试方法:
public class Test {public static void main(String[] args) throws Exception {WorkExperience work = new WorkExperience(); //工作简历实例化Resume a = new Resume("张三",work); //张三的第一份简历a.setPersonalInfo('男', 23);a.setWorkExperience("1996-1999", "IBM");Resume b = (Resume) a.clone();//张三的第二份简历,工作经验有所改动b.setWorkExperience("2000-2002", "Microsoft");System.out.println("第一份简历:");a.display();System.out.println("\n第二份简历:");b.display();}}
运行结果为:
Ps:并没有达到预期的效果,把第一份简历的工作经验也修改了
二、深复制
实例以串行化的方式进行深复制,需实现Serializable接口:
①、原型#########################################
/** *原型,个人简历,实现Cloneable,Serializable接口 */public class Resume implements Cloneable,Serializable{/** *……与浅复制相同部分省略…… */@Overridepublic Object clone(){ //以串行化的方式深度克隆try {//将对象写到流里 ByteArrayOutputStream bo=new ByteArrayOutputStream(); ObjectOutputStream oo=new ObjectOutputStream(bo); oo.writeObject(this); //从流里读出来 ByteArrayInputStream bi=new ByteArrayInputStream(bo.toByteArray()); ObjectInputStream oi=new ObjectInputStream(bi); return oi.readObject();} catch (Exception e) {e.printStackTrace();}return null;}}
②、原型的引用类#########################################
/** *工作简历,实现Serializable接口 */public class WorkExperience implements Serializable{/** *……与浅复制相同部分省略…… */}
再次调用测试方法,运行结果为:
Ps:达到预期的效果,单独修改第二份简历工作经验