在一些情景下面,会需要把一些重复的资料如 简历,模板等进行复制使用,所以要是手动就太麻烦了,所以在java代码设计中就有了原型模式,即克隆模式。
每个需要克隆的类都要有一个Clone方法,并且实现Cloneable接口,不然会报CloneNotSupportedException这个异常。
原型模式有两种状态:浅复制与深复制。
浅复制:调用的是原类型的内存地址,其实跟原先的类一样。
深复制:复制原先的数据,并且在内存中重新开辟一块内存空间,即一个新的对象。
例子如下:
package effective.yuanxing; public class WorkExperience implements Cloneable { private String workDate; public String WorkDate; private String company; public String Company; public String getWorkDate() { return workDate; } public void setWorkDate(String workDate) { this.workDate = workDate; } public String getCompany() { return company; } public void setCompany(String company) { this.company = company; } public Object Clone(){ Object obj = null; try { obj = super.clone(); return obj; } catch (CloneNotSupportedException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("不支持克隆"); return null ; } } }
浅克隆:
package effective.yuanxing; public class Resume implements Cloneable{ private String name; private String sex; private String age; private WorkExperience work; public Resume(String name ){ this.name = name; work = new WorkExperience(); } //设置个人信息 public void SetPersonalInfo(String sex , String age){ this.sex = sex; this.age = age; } //设置工作经历 public void SetWorkExperoence(String workDate , String company){ work.WorkDate = workDate; work.Company = company; } //显示 public void Display(){ System.out.println("name:"+name +"sex:"+sex+"age: "+age); System.out.println("工作经历:"+work.WorkDate+work.Company); } public Object Clone(){ try { return (Object)super.clone(); } catch (CloneNotSupportedException e) { // TODO Auto-generated catch block e.printStackTrace(); return null; } } public static void main(String[] args) { Resume a = new Resume("大鸟"); a.SetPersonalInfo("男", "29"); a.SetWorkExperoence("2015-2018", "XX公司"); Resume b =(Resume)a.Clone(); b.SetPersonalInfo("2016-2018", "yy企业"); Resume c =(Resume)a.Clone(); c.SetPersonalInfo("男", "24"); c.SetWorkExperoence("1998-2003", "zo企业"); a.Display(); b.Display(); c.Display();
System.out.println(a.work==b.work); System.out.println(a.work.Company); } }结果:
name:大鸟sex:男age: 29 工作经历:1998-2003zo企业 name:大鸟sex:2016-2018age: yy企业 工作经历:1998-2003zo企业 name:大鸟sex:男age: 24 工作经历:1998-2003zo企业 true zo企业
可见浅复制的 work对象为同一个对象。并且原来的Company也会被修改,即访问的是原来的对象。
深复制:
package effective.yuanxing; public class DeepResume { private String name; private String sex; private String age; private WorkExperience work; public DeepResume(String name ){ this.name = name; work = new WorkExperience(); } public DeepResume(WorkExperience work){ this.work = (WorkExperience)work.Clone(); } //设置个人信息 public void SetPersonalInfo(String sex , String age){ this.sex = sex; this.age = age; } //设置工作经历 public void SetWorkExperoence(String workDate , String company){ work.WorkDate = workDate; work.Company = company; } //显示 public void Display(){ System.out.println("name:"+name +"sex:"+sex+"age: "+age); } public Object Clone(){ DeepResume obj = new DeepResume(this.work); obj.name = this.name; obj.sex = this.sex; obj.age = this.age; return obj; } public static void main(String[] args) { DeepResume a = new DeepResume("大鸟"); a.SetPersonalInfo("男", "29"); a.SetWorkExperoence("2015-2018", "XX公司"); DeepResume b =(DeepResume)a.Clone(); b.SetPersonalInfo("2016-2018", "yy企业"); DeepResume c =(DeepResume)a.Clone(); c.SetPersonalInfo("男", "24"); c.SetWorkExperoence("1998-2003", "zz企业"); a.Display(); b.Display(); c.Display(); System.out.println(b.work==c.work); System.out.println(a.work.Company); } }
结果:
name:大鸟sex:男age: 29 name:大鸟sex:2016-2018age: yy企业 name:大鸟sex:男age: 24 false XX公司
可见它们的work对象重新创建。
应用场景:类似一个像下围棋 五子棋时,创建棋子的时候就可以用原型模式创建旗子