早就发现java父类有个方法clone(),但一直没用过,也不知道怎么用。直到学习了原型设计模式才明白,他就是克隆方法,专门用来复制对象的。虽然到目前为止还没真正在项目中用到,但克隆方法还是挺有用的,它为我们创建相同对象带来了很大的便利,只要克隆一下就可以拥有一个全新的、初始值跟父类一样的对象。
一、概述
原型模式(Prototype),用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。看这些翻译过来的解释确实好别扭,简单理解就是复制对象,得到全新对象,这个全新对象拥有了跟老对象一样的属性值和方法。
二、结构类图
三、应用实例
没想到更通俗易懂的例子了,就用大话设计模式的例子讲解原型模式吧。大家求职面试都会用到简历,简历书写完毕就很少改动了,应聘不同的公司可以打印一样的简历,我们把打印简历的过程应用到代码层面就是原型模式了。
1、定义简历抽象类
package com.jet.pattern.prototype; import com.jet.pattern.prototype.impl.WorkExperience; /** * description: * 定义简历抽象类(有成员变量和未实现的方法定义抽象类就好) * Created by Administrator on 2017/2/20. */ public abstract class Resume { // 名字 private String name; // 性别 private String sex; // 工作经历 private WorkExperience workExperience ; // 未实现的克隆方法,抛出不支持克隆异常 public abstract Resume Clone() throws CloneNotSupportedException; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public WorkExperience getWorkExperience() { return workExperience; } public void setWorkExperience(WorkExperience workExperience) { this.workExperience = workExperience; } }
2、定义工作经历类
package com.jet.pattern.prototype.impl; /** * description: * 工作经历类 * Created by Administrator on 2017/2/20. */ public class WorkExperience { // 时间 private String time; // 公司 private String company; // 岗位 private String position; public String getTime() { return time; } public void setTime(String time) { this.time = time; } public String getCompany() { return company; } public void setCompany(String company) { this.company = company; } public String getPosition() { return position; } public void setPosition(String position) { this.position = position; } }
3、实现简历类
package com.jet.pattern.prototype.impl; import com.jet.pattern.prototype.Resume; /** * description: * 我的简历实现类,需要实现java的Cloneable接口和自定义的Resume接口 * Created by Administrator on 2017/2/20. */ public class MyResume extends Resume implements Cloneable{ // 实现克隆方法,直接用java父类自带的克隆方法 @Override public Resume Clone() throws CloneNotSupportedException { return (Resume)this.clone(); } }
4、测试类
package com.jet.pattern.prototype.test; import com.jet.pattern.prototype.Resume; import com.jet.pattern.prototype.impl.MyResume; import com.jet.pattern.prototype.impl.WorkExperience; /** * description: * 测试类 * Created by Administrator on 2017/2/20. */ public class MyTest { public static void main(String[] args) throws CloneNotSupportedException { // 创建我的简历 Resume resume = new MyResume(); resume.setName("张晓明"); resume.setSex("男"); WorkExperience workExperience = new WorkExperience(); workExperience.setTime("2014/08/10-2016/08/20"); workExperience.setCompany("智信科技有限公司"); workExperience.setPosition("JAVA开发工程师"); resume.setWorkExperience(workExperience); // 克隆简历 Resume resume1 = resume.Clone(); // 打印简历 System.out.println("----打印简历-----"); System.out.println(resume1.getName()); System.out.println(resume1.getSex()); System.out.println(resume1.getWorkExperience().getTime() + " " + resume1.getWorkExperience().getCompany() + " " + resume1.getWorkExperience().getPosition()); } }
5、测试结果
四、总结
原型模式就是为我们创建相同对象带来便利的,只要有了一个原型对象,之后要创建对象就不用每次都new了,也不用给新创建的对象赋值了,直接调用克隆方法就可以拥有无数可用对象。上面例子中,只要在打印简历代码部分来个for循环,无穷无尽的对象就有了,哈哈。
原型模式中有深度克隆和浅克隆,在浅克隆中需要考虑成员变量对象是否为原生对象(String,Integer等是原生对象),如果是非原生对象还需要层层克隆。而java父类的clone()方法是深度克隆的,我们在例子中也看到了,并没有层层克隆,所以浅克隆就不需过多了解了,java就是那么强大。
其实在java中,自定义的类只要实现了java自带的Cloneable接口就可以被克隆了,并不需要我们自定义一个Clone()方法,本博文是为了讨论原型模式的原理才如此做,在现实项目中不用这般复杂。