【Java】原型模式

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

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

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

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

举一个最简单的例子来说明原型模式:老师把需要做的作业写到黑板上,而下面的我们都要把这些题抄写到自己的本子上,回家做好,第二天交上来,也就是每道题,全班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的信息正是我们想要的,证明原型模式构建成功。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值