设计模式(十五):原型模式
早就发现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()方法,本博文是为了讨论原型模式的原理才如此做,在现实项目中不用这般复杂。