原型模式--简历复印
原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
浅复制:
被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用都仍然指向原来的对象。
如果字段是值类型的,则对该字段执行逐位复制,如果字段是引用类型,则复制引用,不复制引用的对象。因此,原始句柄及其复本引用同一对象。
1 //工作经历类 2 public class WorkExperience { 3 //工作时间 4 private String workDate; 5 6 //工作公司 7 private String company; 8 9 public String getWorkDate() { 10 return workDate; 11 } 12 13 public void setWorkDate(String workDate) { 14 this.workDate = workDate; 15 } 16 17 public String getCompany() { 18 return company; 19 } 20 21 public void setCompany(String company) { 22 this.company = company; 23 } 24 }
1 //简历类 2 public class Resume implements Cloneable{ 3 private String name; 4 private String sex; 5 private String age; 6 7 // 引用"工作经历"对象 8 private WorkExperience work; 9 10 // 构造方法 11 public Resume(String name) { 12 this.name = name; 13 work = new WorkExperience(); 14 } 15 16 // 设置个人信息 17 public void setPersonalInfo(String sex, String age) { 18 this.sex = sex; 19 this.age = age; 20 } 21 22 // 设置工作经历 23 public void setWorkExperience(String workDate, String company) { 24 //调用此方法时,给对象的两属性赋值 25 work.setWorkDate(workDate); 26 work.setCompany(company); 27 } 28 29 // 显示 30 public void display() { 31 System.out.println(name + ":" + sex + ":" + age); 32 // 显示时,显示工作经历的两个属性 33 System.out.println("工作经历:" + work.getWorkDate() + work.getCompany()); 34 } 35 36 //复制对象,浅复制 37 public Resume clone() { 38 Object obj = null; 39 try{ 40 obj = super.clone(); 41 return (Resume) obj; 42 }catch (CloneNotSupportedException e){ 43 System.out.println("不支持复制!"); 44 return null; 45 } 46 } 47 }
测试类:
1 /** 2 * 如果字段是值类型的,则对该字段执行逐位复制,如果字段是引用类型,则复制引用,不复制引用的对象。因此,原始句柄及其复本引用同一对象。 3 * @author 贤元 4 * 5 */ 6 public class Test { 7 public static void main(String[] args) { 8 Resume a = new Resume("大鸟"); 9 a.setPersonalInfo("男", "29"); 10 a.setWorkExperience("1988-2000", " xx公司"); 11 12 Resume b = (Resume) a.clone(); 13 b.setWorkExperience("1988-2003", " yy公司"); 14 15 Resume c = (Resume) a.clone(); 16 c.setWorkExperience("1988-2006", " zz公司"); 17 18 a.display(); 19 b.display(); 20 c.display(); 21 22 /** 23 * 打印结果如下: 24 * 大鸟:男:29 25 工作经历:1988-2006 zz公司 26 大鸟:男:29 27 工作经历:1988-2006 zz公司 28 大鸟:男:29 29 工作经历:1988-2006 zz公司 30 31 */ 32 } 33 }
UML图:
深复制:
把引用对象的变量指向复制过的新对象,而不是原有被引用的对象。
原引用和新引用指向的不是同一个对象,原引用继续指向原来的旧对象,而新引用指向复制过后的新对象(该对象和旧对象中的数据是一样的,但是,该对象不是旧对象,和旧对象是两个完全独立的对象)。
1 //工作经历 2 public class WorkExperience implements Cloneable{ 3 //工作时间 4 private String workDate; 5 //工作公司 6 private String company; 7 public String getWorkDate() { 8 return workDate; 9 } 10 public void setWorkDate(String workDate) { 11 this.workDate = workDate; 12 } 13 public String getCompany() { 14 return company; 15 } 16 public void setCompany(String company) { 17 this.company = company; 18 } 19 20 //注意这里有点不同 21 public WorkExperience clone() { 22 Object obj = null; 23 try{ 24 obj = super.clone(); 25 return (WorkExperience) obj; 26 }catch (CloneNotSupportedException e){ 27 System.out.println("不支持复制!"); 28 return null; 29 } 30 } 31 32 }
1 //简历类 2 public class Resume implements Cloneable { 3 private String name; 4 private String sex; 5 private String age; 6 7 // 引用“工作经历”对象 8 private WorkExperience work; 9 10 // 构造方法 11 public Resume(String name) { 12 this.name = name; 13 work = new WorkExperience(); 14 } 15 16 //构造方法 17 private Resume(WorkExperience work){ 18 //提供clone方法调用的私有构造函数,以便克隆"工作经历"的数据 19 this.work = (WorkExperience)work.clone(); 20 } 21 22 // 设置个人信息 23 public void setPersonalInfo(String sex, String age) { 24 this.sex = sex; 25 this.age = age; 26 } 27 28 // 设置工作经历 29 public void setWorkExperience(String workDate, String company) { 30 // 调用此方法时,给对象的两属性赋值 31 work.setWorkDate(workDate); 32 work.setCompany(company); 33 } 34 35 // 显示 36 public void display() { 37 System.out.println(name + ":" + sex + ":" + age); 38 // 显示时,显示工作经历的两个属性 39 System.out.println("工作经历:" + work.getWorkDate() + work.getCompany()); 40 } 41 42 //进行"深复制"克隆Resume对象 43 public Resume clone(){ 44 //调用私有的构造方法,让“工作经历”克隆完成,然后再给这个“简历”对象的相关字段赋值,最终返回一个深复制的简历对象。 45 Resume obj = new Resume(this.work); 46 obj.name = this.name; 47 obj.sex = this.sex; 48 obj.age = this.age; 49 50 //以上四行代码是重新封装一个一模一样的Resume对象,内容是一样的,但是他们的引用指向的是两个独立的对象,就相当于复制的不是引用,而是一个完整的对象 51 return obj; 52 } 53 54 }
测试类:
1 /** 2 * 如果字段是值类型的,则对该字段执行逐位复制,如果字段是引用类型,则复制引用,不复制引用的对象。因此,原始句柄及其复本引用同一对象。 3 * @author 贤元 4 * 5 */ 6 public class Test { 7 public static void main(String[] args) { 8 Resume a = new Resume("大鸟"); 9 a.setPersonalInfo("男", "29"); 10 a.setWorkExperience("1988-2000", " xx公司"); 11 12 Resume b = a.clone();//深复制 13 b.setWorkExperience("1988-2003", " yy公司"); 14 15 Resume c = a.clone();//深复制 16 c.setWorkExperience("1988-2006", " zz公司"); 17 18 a.display(); 19 b.display(); 20 c.display(); 21 22 /** 23 * 打印结果如下: 24 * 大鸟:男:29 25 工作经历:1988-2000 xx公司 26 大鸟:男:29 27 工作经历:1988-2003 yy公司 28 大鸟:男:29 29 工作经历:1988-2006 zz公司 30 31 */ 32 } 33 }
UML图:
不能只满足于写完代码运行结果正确就完事,时常考虑如何让代码更加简练更加容易维护、容易扩展和复用,只有这样才可以真正得到提高
--《来自大话设计模式》