您的位置:首页 > 编程语言 > Java开发

【Java】原型模式

2015-10-10 15:18 375 查看
对于设计模式,网上大部分资料都直接抛出一大堆理论,让人难以看明白。其实所谓的“设计模式”,只是怎么把代码写得更好而已,避免大量的代码出现重复而已,如果你不介意,完全可以把某一段代码拷贝粘贴多次,来实现功能,然而,许多地方,甚至软考的软件设计师,都对设计模式进行考察。

下面说说原型模式,其实设计模式,任何语言都能实现,是一种编程思想。

原型模式是:通过复制一个已经存在的实例来创建一个新的实例。被复制的实例被称为原型,这个原型是可定制的。

原型模式的作用是:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

举一个最简单的例子来说明原型模式:老师把需要做的作业写到黑板上,而下面的我们都要把这些题抄写到自己的本子上,回家做好,第二天交上来,也就是每道题,全班50个人,每个人都要抄写一遍。按照现在的时间理论来说,就是浪费了50个人的时间。

现在,老师做一份电子版的习题,打印一份,然后拿着这份打印的原版,就可以复制出50份。

结合原型模式的概念进行分析,老师打印出来的那一份,就是“原型”,而复制出来的那50份,就是使用的“拷贝”。而原型模式就是这么简单的一个道理,通过现有的东西,再复制出一个来。

以2013年上半年的软件设计师的软考的最后一题(以Java作答)说明原型模式的应用。

题目是这样的:现要求实现一个能够自动生成求职简历的程序。简历的基本内容包括求职者的姓名、性别、年龄以及工作经历等。希望每份简历的工作经历有所不同,并尽量减少程序中重复的代码。

现采用原型(Prototype)模式来实现上述要求,得到如图6-1所示的类图:



也就是说,在Resume a,Resume b大量的信息,也就是姓名、年龄这些类成员是完全一样的的,只有里面的WorkExperience中的内容,但你不可以在初始化Resume a与Resume b的时候,搞出Resume a("张三","29","男“,"1999-2002","XX公司"),Resume b("张三","29","男“,"2002-2006","YY公司")公司这样的初始化来,需要Resume  b直接复制Resume a的内容,然后利用其中的set的方法,来改变其中的"1999-2002","XX公司"两项。

据说使用原型模式创建对象比直接new一个对象在性能上要好的多,因为Object类的clone方法是一个本地方法,它直接操作内存中的二进制流,特别是复制大对象时,性能的差别非常明显。

具体代码如下,其中用到Cloneable接口。在java语言有一个Cloneable接口,它的作用只有一个,就是在运行时通知虚拟机可以安全地在实现了此接口的类上使用clone方法。在java虚拟机中,只有实现了这个接口的类才可以被拷贝,否则在运行时会抛出CloneNotSupportedException异常。重写Object类中的clone方法。Java中,所有类的父类都是Object类,Object类中有一个clone方法,作用是返回对象的一个拷贝,但是其作用域protected类型的,一般的类无法调用,因此,Prototype类需要将clone方法的作用域修改为public类型。这比C++还要自己定义一个Cloneable接口简单得多,因为Java本身自带。

class WorkExperience implements Cloneable{

private String workDate;
private String company;
public Object Clone(){
WorkExperience obj= new WorkExperience();
obj.workDate=this.workDate;
obj.company=this.company;
return obj;
}

//getter setter,只是为了数据的传递。原题目这段代码被省略了。
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;
}
}

class Resume implements Cloneable{

private String name;
private String sex;
private String age;
private WorkExperience work;

public Resume(String name){//初始化的时候,WorkExperience为空
this.name=name;
work=new WorkExperience();
}
private Resume(WorkExperience work){
//构建Resume类的时候,自动将所有的WorkExperience信息复制过去
this.work=work;
}
public void SetPersonalInfo(String sex,String age){
this.sex=sex;
this.age=age;
}
public void SetWorkExperience(String workDate,String company){//用于改变WorkExperience信息
work.setWorkDate(workDate);
work.setCompany(company);
}
public Object Clone(){//复制原型的时候,将WorkExperience信息+所有类成员复制过去。
Resume obj= new Resume(work);
obj.name=this.name;
obj.sex=this.sex;
obj.age=this.age;
return obj;
}

//getter setter,只是为了数据的传递。原题目这段代码被省略了。
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 String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public WorkExperience getWork() {
return work;
}
public void setWork(WorkExperience work) {
this.work = work;
}
}

public class WorkResume {
public static void main(String[] args) {
//Resume a成功构建,并设置信息之后
Resume a= new Resume("张三");
a.SetPersonalInfo("男","29");
a.SetWorkExperience("1998-2000", "XXX公司");
//Resume b直接复制a信息,再改变SetWorkExperience
Resume b=(Resume)a.Clone();
b.SetWorkExperience("2001-2006", "YYY公司");
//打印测试Resume b的信息
System.out.println(b.getName()+","+b.getAge()+","+b.getSex()+","+b.getWork().getWorkDate()+","+b.getWork().getCompany());
}
}


b并没有初始化,只是直接拷贝a的内容,改变工作经历,但打印B的信息,发现B的信息正是我们想要的,证明原型模式构建成功。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: