【设计模式】原型模式--------java

23 篇文章 0 订阅
22 篇文章 0 订阅

原型模式:
1.问题引入:(简历)

public class Test {
	public static void main(String[] args) {
		Resume a=new Resume("大鸟");
		a.setPersonnalInfo("男", "29");
		a.setWorkExperience("1998-2000","XX公司");
		
		Resume b=new Resume("大鸟");
		b.setPersonnalInfo("男", "29");
		b.setWorkExperience("1998-2000","XX公司");
		
		Resume c=new Resume("大鸟");
		c.setPersonnalInfo("男", "29");
		c.setWorkExperience("1998-2000","XX公司");
		
		a.display();b.display();c.display();
	}
}

//简历类
class Resume{
	private String name;
	private String sex;
	private String age;
	private String timeArea;
	private String company;
	
	public Resume(String name) {
		this.name=name;
	}
	public void setPersonnalInfo(String sex,String age) {
		this.sex=sex;
		this.age=age;
	}
	public void setWorkExperience(String timeArea,String company) {
		this.timeArea=timeArea;
		this.company=company;
	}
	public void display() {
		System.out.println(name+" "+sex+" "+age);
		System.out.println("工作经历:"+timeArea+" "+company);
	}
	
}

缺点:三份简历需要三次实例化,麻烦。

注:这里不能将客户端代码改为Resume b=a; 这是引用,一改都改。

2.改进:原型模式(浅复制)
用复制原型对象的方法创建出更多的同类型对象。
用到java.lang.Cloneable接口的clone()方法。

package computer;

public class Test {
	public static void main(String[] args) {
		Resume a=new Resume("大鸟");
		a.setPersonnalInfo("男", "29");
		a.setWorkExperience("1998-2000","XX公司");
		
		Resume b=a.clone();
		b.setWorkExperience("1998-2006","YY企业");
		
		Resume c=a.clone();
		c.setPersonnalInfo("男", "4");
		
		a.display();b.display();c.display();
	}
}

//简历类
class Resume implements Cloneable{
	private String name;
	private String sex;
	private String age;
	private String timeArea;
	private String company;
	
	public Resume(String name) {
		this.name=name;
	}
	public void setPersonnalInfo(String sex,String age) {
		this.sex=sex;
		this.age=age;
	}
	public void setWorkExperience(String timeArea,String company) {
		this.timeArea=timeArea;
		this.company=company;
	}
	public void display() {
		System.out.println(name+" "+sex+" "+age);
		System.out.println("工作经历:"+timeArea+" "+company);
	}
	
	//克隆
	public Resume clone() {
		try {
			return (Resume)super.clone();
		}
		catch(CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return null;
	}
}

优点:修改简历只需要修改一份。不用每次都执行构造函数。
Clone()方法缺点:对于引用类型,只复制引用但不复制引用的对象(仍一改多改)。即“简历”类中若有对象引用,那么引用的对象数据不会被克隆。

3.简历类中有其他类的对象的情况:

package computer;

public class Test {
	public static void main(String[] args) throws CloneNotSupportedException {
		Resume a = new Resume("大鸟");
		a.setPersonnalInfo("男", "29");
		a.setWorkExperience("1998-2000", "XX公司");

		Resume b = a.clone();
		b.setWorkExperience("1998-2006", "YY企业");

		Resume c = a.clone();
		c.setWorkExperience("1998-2003", "ZZ企业");

		a.display();
		b.display();
		c.display();
	}
}

//工作经历类
class WorkExperience {
	private String workDate;
	private String company;

	public String getWorkDate() {
		return workDate;
	}

	public String getCompany() {
		return company;
	}

	public void setWorkDate(String workDate) {
		this.workDate = workDate;
	}

	public void setCompany(String company) {
		this.company = company;
	}
}

//简历类
class Resume implements Cloneable {
	private String name;
	private String sex;
	private String age;
	// 工作经历类对象
	private WorkExperience work = new WorkExperience();

	public Resume(String name) {
		this.name = name;
	}

	public void setPersonnalInfo(String sex, String age) {
		this.sex = sex;
		this.age = age;
	}

	public void setWorkExperience(String workDate, String company) {
		work.setWorkDate(workDate);
		work.setCompany(company);
	}

	public void display() {
		System.out.println(name + " " + sex + " " + age);
		System.out.println("工作经历:" + work.getWorkDate() + " " + work.getCompany());
	}

	// 克隆的另一种写法:
	public Resume clone() throws CloneNotSupportedException {
		return (Resume) super.clone();
	}

}

出错原因:三个引用都指向了同一个对象。

4.改进:原型模式(深复制):
在这里插入图片描述

package computer;

public class Test {
	public static void main(String[] args) throws CloneNotSupportedException {
		Resume a = new Resume("大鸟");
		a.setPersonnalInfo("男", "29");
		a.setWorkExperience("1998-2000", "XX公司");

		Resume b = a.clone();
		b.setWorkExperience("1998-2006", "YY企业");

		Resume c = a.clone();
		c.setWorkExperience("1998-2003", "ZZ企业");

		a.display();
		b.display();
		c.display();
	}
}

//工作经历类
class WorkExperience implements Cloneable{
	private String workDate;
	private String company;

	public String getWorkDate() {
		return workDate;
	}

	public String getCompany() {
		return company;
	}

	public void setWorkDate(String workDate) {
		this.workDate = workDate;
	}

	public void setCompany(String company) {
		this.company = company;
	}
	
	public WorkExperience clone() {
		try {
			return (WorkExperience)super.clone();
		}
		catch(CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return null;
	}
}

//简历类
class Resume implements Cloneable {
	private String name;
	private String sex;
	private String age;
	// 工作经历类对象
	private WorkExperience work = new WorkExperience();

	public Resume(String name) {
		this.name = name;
	}

	public void setPersonnalInfo(String sex, String age) {
		this.sex = sex;
		this.age = age;
	}

	public void setWorkExperience(String workDate, String company) {
		work.setWorkDate(workDate);
		work.setCompany(company);
	}

	public void display() {
		System.out.println(name + " " + sex + " " + age);
		System.out.println("工作经历:" + work.getWorkDate() + " " + work.getCompany());
	}

	//深复制
	public Resume clone() {
		Resume r=new Resume(name);
		r.sex=this.sex;
		r.age=this.age;
		r.work=this.work;
//this.work.clone()调用工作经历类的复制函数,工作经历类中没有引用的对象,可以避免复制引用的情况。即通过this.work.clone()复制出一个新的工作经历类对象a,再通过r.work=this.work.clone()让要复制出来的简历类对象中的工作经历类对象指向对象a。
		r.work=this.work.clone();
		return r;
	}
}

5.原型模式的结构:
在这里插入图片描述
(浅复制为例):

package computer;

public class Test {
	public static void main(String[] args) throws CloneNotSupportedException {
		Resume a = new Resume("大鸟");
		a.setPersonnalInfo("男", "29");
		a.setWorkExperience("1998-2000", "XX公司");

		Resume b = a.clone();
		b.setWorkExperience("1998-2006", "YY企业");

		Resume c = a.clone();
		c.setWorkExperience("1998-2003", "ZZ企业");

		a.display();
		b.display();
		c.display();
	}
}

//抽象原型类
class Prototype implements Cloneable {
	private String id;

	public Prototype(String id) {
		this.id = id;
	}

	public String getId() {
		return id;
	}

	public Prototype clonePrototype() {
		return null;
	}
}

//具体原型类1
class ConcretePrototype1 extends Prototype {
	public ConcretePrototype1(String id) {
		super(id);
	}

	// 返回值类型为父类类型原因:继承父类该函数,故返回值不变
	public Prototype clonePrototype() {
		try {
			// 强制类型转换为父类类型原因:返回值类型为父类类型
			return (Prototype) super.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return null;
	}
}

//具体原型类2
class ConcretePrototype2 extends Prototype {
	public ConcretePrototype2(String id) {
		super(id);
	}

	// 返回值类型为父类类型原因:继承父类该函数,故返回值不变
	public Prototype clonePrototype() {
		try {
			// 强制类型转换为父类类型原因:返回值类型为父类类型
			return (Prototype) super.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return null;
	}
}

原型模式一定程度上可以代替工厂模式:
工厂模式实现的生产产品的功能:生产的产品是由同一个抽象产品类派生出来的,即要生产一类产品就要引入一个抽象产品类,再由它派生出具体的几种产品。
原型模式中,可以同样定义“抽象产品-具体产品”的层次,再利用clone功能来产生具体产品本身来实现工厂模式的功能。即,原型模式中,每个具体的产品就扮演了工厂模式的具体工厂的角色(因为每个具体产品都具有生成自己拷贝的功能,这正是工厂的作用)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值