设计模式之原型模式
程序员文章站
2022-03-13 10:24:35
找工作时我们经常需要复印几份相同的简历。如果用编程来实现就是简单的复制粘贴,我们觉得很理所当然。 可以看出我们需要几份简历就需要实例化几次。如果写错一个字,也得改很多次。那有没有一种更简洁的方式呢?那就是原型模式了 原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。 我们用原 ......
找工作时我们经常需要复印几份相同的简历。如果用编程来实现就是简单的复制粘贴,我们觉得很理所当然。
public class Resume { private String name; private String sex; private String age; private String timeArea; private String company; public Resume(String name){ this.name = name; } //设置个人信息 public void setPersonalInfo(String sex, String age){ this.sex = sex; this.age = age; } //设置工作经历 public void setWorkExperience(String timeArea, String company){ this.timeArea = timeArea; this.company = company; } public void show(){ System.out.println(name + " " + age + " " + sex); System.out.println("工作经历:" + timeArea + " " + company); } } public class Test{ public static void main(String[] args){ Resume resume1 = new Resume("zhangsan"); resume1.setPersonalInfo("boy", "28"); resume1.setWorkExperience("2016.3-2018.4", "xxxx company"); Resume resume2 = new Resume("wangmazi"); resume2.setPersonalInfo("girl", "18"); resume2.setWorkExperience("2015.3-2018.9", "xxxx company"); resume1.show(); resume2.show(); } }
可以看出我们需要几份简历就需要实例化几次。如果写错一个字,也得改很多次。那有没有一种更简洁的方式呢?那就是原型模式了
原型模式:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
我们用原型模式来实现一下简历复制。
public class Resume3 implements Cloneable{ private String name; private String sex; private String age; private WorkExperience we = new WorkExperience(); public Resume3(String name){ this.name = name; } //设置个人信息 public void setPersonalInfo(String sex, String age){ this.sex = sex; this.age = age; } //设置工作经历 public void setWorkExperience(String timeArea, String company){ we.setTimeArea(timeArea); we.setCompany(company); } public void show(){ System.out.println(name + " " + age + " " + sex); System.out.println("工作经历:" + we.getTimeArea() + " " + we.getCompany()); } public Object clone() throws CloneNotSupportedException{ return super.clone(); } public static void main(String[] args) throws CloneNotSupportedException{ Resume3 resume1 = new Resume3("zhangsan"); resume1.setPersonalInfo("boy", "28"); resume1.setWorkExperience("2016.3-2018.4", "xxxx company"); //浅复制 Resume3 resume2 = (Resume3)resume1.clone(); resume2.setWorkExperience("2015.3-2018.9", "xxxx company"); resume1.show(); resume2.show(); } }
这样代码就清爽多了,复制一份简历也非常简单。通过new方式创建对象需要每次都执行构造函数,非常低效。所以一般在初始化的信息不发生变化的情况下,克隆是最好的办法,既隐藏了对象创建的细节,又大大提高了性能。
但这其中也有问题,clone方法是这样的,如果字段是值类型,则对改字段执行逐位复制,如果字段是引用类型,则复制引用但不复制引用的对象,也就是说引用对象数据不会克隆过来。这就称为浅复制。从上面例子也可以看出,改变resume2的workExperience对象中的数据也会改变resume1的workExperience对象中的数据,因为他们是指向同一个引用。
那如何进行深复制呢?
public class Resume4 implements Cloneable{ private String name; private String sex; private String age; private WorkExperience2 we; public Resume4(String name){ this.name = name; we = new WorkExperience2(); } public Resume4(WorkExperience2 workExperience) throws CloneNotSupportedException{ this.we = (WorkExperience2) workExperience.clone(); } //设置个人信息 public void setPersonalInfo(String sex, String age){ this.sex = sex; this.age = age; } //设置工作经历 public void setWorkExperience(String timeArea, String company){ we.setTimeArea(timeArea); we.setCompany(company); } public void show(){ System.out.println(name + " " + age + " " + sex); System.out.println("工作经历:" + we.getTimeArea() + " " + we.getCompany()); } public Object clone() throws CloneNotSupportedException{ Resume4 resume = new Resume4(this.we); resume.name = this.name; resume.age = this.age; resume.sex = this.sex; return resume; } public static void main(String[] args) throws CloneNotSupportedException{ Resume4 resume1 = new Resume4("zhangsan"); resume1.setPersonalInfo("boy", "28"); resume1.setWorkExperience("2016.3-2018.4", "xxxx company"); //深复制 Resume4 resume2 = (Resume4)resume1.clone(); resume2.setWorkExperience("2015.4-2018.9", "xxxx company"); resume1.show(); resume2.show(); } }
这就是深复制,深复制把引用对象的变量指向复制过的对象,而不是原有的被引用的对象。我们发现如果引用中嵌套多层引用,深复制就变得很复杂,需要事先考虑清楚,小心处理。
下一篇: 遗忘的html标签