设计模式-原型模式

一、原型模式
定义:用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。
原型模型其实是从一个对象再创建另外一个可定制的对象,而且不需要知道任何创建的细节。
类型:创建型类型
优点和使用场景:1.使用原型模型创建对象比直接new一个对象在性能上要好的多,原因是Object的clone方法是一个本地方法,直接操作内存中的二进制流。2.简化对象的创建。
注意事项-深拷贝和浅拷贝
Object的clone方法只会拷贝对象中的基本数据类型,对于数组、容器对象、引用对象等都不会拷贝,这就是浅拷贝。要实现深拷贝,需要在重写clone方法时,将原型模型中的数组、容器对象和引用对象等进行拷贝。
二、UML类图
原型类Protype需具备以下两个条件:
1.实现Cloneable接口。java语言的cloneable接口的作用只有一个:在运行时通知虚拟机可以安全地在此接口的类上使用clone方法。在java虚拟机中,只有实现这个接口的类才可以被拷贝,否则在运行时会抛出CloneNotSupportedException。
2.重写Object类的clone方法。Java中所有类的父类是Object类,Object类中有一个clone方法,是本地方法,作用时返回对象的一个拷贝,但作用域是protected,因此Protype类需要将clone方法的作用域变为public。
Protype实现一个接口,并重写clone方法,即可完成原型模式。实际应用中,原型模型很少单独出现,经常与其他模型混用,因此Protype类常用抽象类替代。

三、具体案例
参考大话设计模式-简历的复制。
浅复制:
java实现代码:
public class PrototypeDesign {
	public static void main(String[] args){
		Resume resume=new Resume("ff");
		resume.setPersonalInfl(24, "男");
		resume.setWorkExperience("2017-05-02", "mt");
		resume.display();
		//resume2 拷贝了resume
		Resume resume2=resume.clone();
		resume2.setPersonalInfl(20, "女");
		resume2.setWorkExperience("2017-05-02", "didi");
		//对resume2进行修改,观察resume和resume2的变化
		System.out.println("对resume2修改后:");
		resume2.display();
		resume.display();
	}
}
class Resume implements Cloneable{
	private String name;
	private int age;
	private String sex;
	private Experience experience;

	public Resume(String name){
		this.name=name;
		this.experience=new Experience();
	}
	public void setPersonalInfl(int age,String sex){
		this.age=age;
		this.sex=sex;
	}
	public void setWorkExperience(String timeArea,String company){
		this.experience.timeArea=timeArea;
		this.experience.company=company;
	}
	public void display(){
		System.out.println(name+" "+sex+" "+age);
		System.out.println(experience.timeArea+" "+experience.company);
	}
	public Resume clone() {
		Resume resume=null;
		try{
			resume=(Resume)super.clone();
		}catch(CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return resume;
	}
}
class Experience{
	public String timeArea;
	public String company;
}
实现结果:
ff 男 24
2017-05-02 mt
对resume2修改后:
ff 女 20
2017-05-02 didi
ff 男 24
2017-05-02 didi
结果分析:
程序先创建了一个resume对象,resume2对象对其进行了拷贝并修改了性别(String)、年龄(int)、工作经历(Experience),结果resume对象的工作经历也被修改了。由此证明了 浅拷贝只拷贝对象的基本类型,而不拷贝对象包含的引用指向的对象。
深拷贝:
java实现代码:
public class PrototypeDesign {
	public static void main(String[] args){
		Resume resume=new Resume("ff");
		resume.setPersonalInfl(24, "男");
		resume.setWorkExperience("2017-05-02", "mt");
		resume.display();
		//resume2 拷贝了resume
		Resume resume2=resume.clone();
		resume2.setPersonalInfl(20, "女");
		resume2.setWorkExperience("2017-05-02", "didi");
		//对resume2进行修改,观察resume和resume2的变化
		System.out.println("对resume2修改后:");
		resume2.display();
		resume.display();
	}
}
class Resume implements Cloneable{
	private String name;
	private int age;
	private String sex;
	private Experience experience;

	public Resume(String name){
		this.name=name;
		this.experience=new Experience();
	}
	public void setPersonalInfl(int age,String sex){
		this.age=age;
		this.sex=sex;
	}
	public void setWorkExperience(String timeArea,String company){
		this.experience.timeArea=timeArea;
		this.experience.company=company;
	}
	public void display(){
		System.out.println(name+" "+sex+" "+age);
		System.out.println(experience.timeArea+" "+experience.company);
	}
	public Resume clone() {
		Resume resume=null;
		try{
			resume=(Resume)super.clone();
			resume.experience=resume.experience.clone();
		}catch(CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return resume;
	}
}
class Experience implements Cloneable{
	public String timeArea;
	public String company;
	public Experience clone(){
		Experience experience=null;
		try {
			experience=(Experience)super.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return experience;
	}
}
实现结果:
ff 男 24
2017-05-02 mt
对resume2修改后:
ff 女 20
2017-05-02 didi
ff 男 24
2017-05-02 mt
结果分析:
将Resume类的成员变量Experience也实现Cloneable接口并重新clone方法,同时在Resume类的clone方法中,对Experience引用对象进行另外拷贝,从而实现了深拷贝。
参考:
2.大话设计模式

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值