【Java】原型模式

本文详细解析了设计模式中的原型模式概念及其应用。通过一个简单例子,阐述了原型模式如何通过复制现有实例来创建新实例,节省时间和资源。接着,通过Java编程语言的具体案例,展示了原型模式在生成不同求职简历程序中的实际运用,强调了其在减少代码重复和提高性能方面的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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

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

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

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


<think>嗯,用户想了解Java中的原型模式实现和用法。首先,我需要回顾一下原型模式的基本概念,确保自己理解正确。原型模式属于创建型设计模式,用于通过复制有对象来创建新对象,而不是通过实例化类。这样可以避免重复初始化对象的开销,特别是当对象的创建成本较高时。 接下来,我应该虑用户可能的背景。用户可能已经对设计模式有一定的了解,比如单例模式、策略模式等,但需要具体了解原型模式。用户的问题集中在实现和示例上,所以需要详细说明如何用Java实现原型模式,并提供代码示例。 首先,要明确原型模式的核心:实现Cloneable接口并重写clone()方法。Java中的Cloneable是一个标记接口,没有方法,但需要类实现它才能调用Object的clone()方法。需要注意的是,clone()方法默认是浅拷贝,如果对象包含引用类型的字段,可能需要深拷贝。这一点用户可能会忽略,所以在回答中需要特别指出。 然后,需要举一个具体的例子。比如,创建一个Person类,包含基本类型和引用类型的字段(如List<String> hobbies),然后展示浅拷贝和深拷贝的区别。这样用户能直观地看到不同实现方式的影响。 另外,用户可能想知道原型模式的适用场景。比如,当对象创建成本高,或者系统需要动态配置多个组合对象时。这部分需要结合实际应用场景,让用户理解何时使用该模式。 还要虑用户可能遇到的问题,例如如何实现深拷贝。除了重写clone()方法进行深拷贝,还可以提到其他方法,如序列化/反序列化,或者使用第三方库。但主要应集中在标准的Cloneable实现上,避免让用户感到困惑。 需要检查是否有相关的引用内容可以引用。用户提供的引用中有提到原型模式[^1],但其他引用是关于状态模式和策略模式的,可能不直接相关。因此,在回答中应正确引用已有的相关内容,确保引用标识符对应正确。 最后,生成相关问题,帮助用户进一步学习。比如原型模式与工厂模式的区别,深拷贝与浅拷贝的注意事项,以及如何选择不同的创建型模式。这些问题应该围绕原型模式展开,帮助用户深化理解。 总结步骤: 1. 定义原型模式及其目的。 2. 实现步骤:Cloneable接口和clone()方法。 3. 代码示例,展示浅拷贝和深拷贝。 4. 适用场景。 5. 注意事项,如深拷贝的必要性。 6. 引用相关的内容(如果有)。 7. 生成相关问题。 确保回答结构清晰,代码正确,并且用中文自然表达。避免使用复杂术语,让不同层次的用户都能理解。</think>### Java原型模式实现与示例 #### 一、原型模式定义 原型模式(Prototype Pattern)通过复制有对象来创建新对象,而不是通过`new`关键字实例化。这种方式适用于**对象创建成本较高**的场景(例如需要复杂初始化流程或涉及大量数据加载),或需要动态配置对象的场景。 --- #### 二、核心实现步骤 1. **实现`Cloneable`接口** Java中需实现标记接口`Cloneable`,否则调用`clone()`方法会抛出`CloneNotSupportedException`。 2. **重写`clone()`方法** 覆盖`Object`类的`clone()`方法,并指定为`public`访问权限。 --- #### 三、代码示例 ##### 1. 基础原型类 ```java class Person implements Cloneable { private String name; private List<String> hobbies; // 引用类型字段 public Person(String name, List<String> hobbies) { this.name = name; this.hobbies = hobbies; } @Override public Person clone() { try { // 浅拷贝 return (Person) super.clone(); } catch (CloneNotSupportedException e) { throw new AssertionError(); // 不会发生 } } // 深拷贝实现 public Person deepClone() { List<String> newHobbies = new ArrayList<>(this.hobbies); return new Person(this.name, newHobbies); } } ``` ##### 2. 使用示例 ```java public class PrototypeDemo { public static void main(String[] args) { // 原始对象 List<String> hobbies = new ArrayList<>(Arrays.asList("Reading", "Music")); Person original = new Person("Alice", hobbies); // 浅拷贝(共享hobbies引用) Person shallowCopy = original.clone(); shallowCopy.getHobbies().add("Swimming"); // 深拷贝(独立hobbies对象) Person deepCopy = original.deepClone(); deepCopy.getHobbies().add("Running"); System.out.println("Original hobbies: " + original.getHobbies()); // 输出:[Reading, Music, Swimming] } } ``` --- #### 四、适用场景 1. **资源密集型对象创建** 如数据库连接、文件解析后的对象缓存。 2. **动态组合对象** 当系统需要多种对象组合且组合方式频繁变化时,通过原型复制可快速生成新配置。 3. **避免构造器约束** 绕过复杂构造逻辑直接复制有对象。 --- #### 五、注意事项 1. **浅拷贝与深拷贝** 默认`clone()`是浅拷贝,若对象包含引用类型字段(如集合、自定义类),需手动实现深拷贝(如示例中的`deepClone()`)。 2. **性能权衡** 深拷贝可能增加内存和计算开销,需根据场景选择。 3. **Cloneable接口的局限性** Java的`clone()`方法设计较为笨拙,可通过序列化/反序列化或第三方库(如Apache Commons Lang)实现更灵活的拷贝。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值