被说了很多遍的设计模式---原型模式

[把你的理性思维慢慢变成条件反射]

本文,我们讲介绍原型模式,文章主题结构与上位一致。惯例,先来看看我们示例工程的环境:

操作系统:win7 x64

其他软件:eclipse mars,jdk7

-------------------------------------------------------------------------------------------------------------------------------------

经典问题:

对象复制,克隆。

思路分析:

要点一:支持浅克隆。

要点二:支持深克隆。

示例工程:


错误写法:

创建Templet.java文件,具体内容如下:

package com.csdn.ingo.gof_prototype;

public class Window {
	public static void main(String[] args) {
		Templet a = new Templet("TempletA");
		a.setContext("AAAAA");
		a.setTime("010101");
		a.setCompany("CompanyA");
		
		Templet b = a;
		b.setName("TempletB");
		Templet c = a;
		c.setName("TempletC");
		
		a.display();
		b.display();
		c.display();
		System.out.println(a.hashCode());
		System.out.println(b.hashCode());
		System.out.println(c.hashCode());
	}
}

错误原因:

首先,我们先观察上面main方法输出内容:

name:TempletC,context:AAAAA,time:010101,company:CompanyA
name:TempletC,context:AAAAA,time:010101,company:CompanyA
name:TempletC,context:AAAAA,time:010101,company:CompanyA
17198255
17198255
17198255
ABC三个对象在内存当中的地址完全相同,即代表同一个对象。(这部分概念非常基础,请各位看官牢记)。

推荐写法(1):浅克隆(值类型)


创建Prototype.java文件,具体内容如下:

package com.csdn.ingo.gof_prototype.one;

public abstract class Prototype {
	
	private String id;
	
	public Prototype(String id){
		this.id=id;
	}
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	
	public abstract Prototype Clone();
}
创建ConcretePrototypeA文件,具体内容如下:

package com.csdn.ingo.gof_prototype.one;

public class ConcretePrototypeA extends Prototype implements Cloneable {

	public ConcretePrototypeA(String id) {
		super(id);
	}

	@Override
	public Prototype Clone() {
		return (Prototype) this.clone();
	}

	@Override
	public Object clone() {
		ConcretePrototypeA cpa = null;
		try {
			cpa = (ConcretePrototypeA) super.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return cpa;
	}
}
创建Window.java文件,具体内容如下:

package com.csdn.ingo.gof_prototype.one;

public class Window {
	public static void main(String[] args) {
		ConcretePrototypeA a = new ConcretePrototypeA("ingo");
		ConcretePrototypeA b = (ConcretePrototypeA)a.Clone();
		System.out.println(a.hashCode());
		System.out.println(b.hashCode());
	}
}
观察输出:

1149197
20761102

推荐写法(2):浅克隆(引用类型)


创建Collection.java文件,具体内容如下:

package com.csdn.ingo.gof_prototype.two;

import com.csdn.ingo.gof_prototype.one.ConcretePrototypeA;

public class Collection implements Cloneable {
	private String prop1;
	private String prop2;
	
	public String getProp1() {
		return prop1;
	}
	public void setProp1(String prop1) {
		this.prop1 = prop1;
	}
	public String getProp2() {
		return prop2;
	}
	public void setProp2(String prop2) {
		this.prop2 = prop2;
	}
	@Override
	public Object clone() {
		Collection co = null;
		try {
			co = (Collection) super.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return co;
	}
}
创建ConcretePrototypeA.java文件,具体内容如下:
package com.csdn.ingo.gof_prototype.two;

public class ConcretePrototypeA extends Prototype implements Cloneable {
	private Collection collection =new Collection();
	
	public Collection getCollection() {
		return collection;
	}

	public void setCollection(Collection collection) {
		this.collection = collection;
	}

	public ConcretePrototypeA(String id) {
		super(id);
	}

	@Override
	public Prototype Clone() {
		return (Prototype) this.clone();
	}

	@Override
	public Object clone() {
		ConcretePrototypeA ca = null;
		try {
			ca = (ConcretePrototypeA) super.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return ca;
	}
}
创建Prototype.java文件,具体内容如下:

package com.csdn.ingo.gof_prototype.two;

public abstract class Prototype {
	
	private String id;
	
	public Prototype(String id){
		this.id=id;
	}
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	
	public abstract Prototype Clone();
}
创建Window.java文件,具体内容如下:

package com.csdn.ingo.gof_prototype.two;

public class Window {
	public static void main(String[] args) {
		ConcretePrototypeA a = new ConcretePrototypeA("ingo");
		ConcretePrototypeA b = (ConcretePrototypeA)a.Clone();
		Collection ca = a.getCollection();
		ca.setProp1("a1");
		ca.setProp2("a2");
		Collection cb = b.getCollection();
		cb.setProp1("b1");
		cb.setProp2("b2");
		System.out.println(a.hashCode());
		System.out.println(b.hashCode());
		System.out.println(a.getCollection().hashCode());
		System.out.println(b.getCollection().hashCode());
	}
}
观察输出:

1396421
15105042
31164770
31164770

推荐写法(3):深克隆(专用)


创建Colleation.java文件,具体内容如下:

package com.csdn.ingo.gof_prototype.three;

import com.csdn.ingo.gof_prototype.two.ConcretePrototypeA;

public class Collection implements Cloneable{
	
	private String date;
	private String company;
	public String getDate() {
		return date;
	}
	public void setDate(String date) {
		this.date = date;
	}
	public String getCompany() {
		return company;
	}
	public void setCompany(String company) {
		this.company = company;
	}
	@Override
	public Object clone(){
		Collection ca = null;
		try {
			ca = (Collection) super.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return ca;
	}
	@Override
	public String toString() {
		return "Collection [date=" + date + ", company=" + company + "]";
	}
}
创建Prototype.java文件,具体内容如下:
package com.csdn.ingo.gof_prototype.three;

public class Prototype implements Cloneable {
	private String name;
	private Collection work;
	public Prototype(String name){
		this.name = name;
		work = new Collection();
	}
	private Prototype(Collection work){
		this.work = (Collection)work.clone();
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Collection getWork() {
		return work;
	}
	public void setWork(Collection work) {
		this.work = work;
	}
	public void setWke(String date,String company){
		work.setDate(date);
		work.setCompany(company);
	}
	@Override
	public String toString() {
		return "Prototype [name=" + name + ", work=" + work.toString() + "]";
	}
	@Override
	public Object clone(){
		Prototype ca = new Prototype(this.work);
		ca.setName(name);
		return ca;
	}
}
创建Window.java文件,具体内容如下:
package com.csdn.ingo.gof_prototype.three;

public class Window {

	public static void main(String[] args) {
		Prototype a = new Prototype("ingo");
		System.out.println(a.hashCode());
		a.setWke("01", "aaa");
		Prototype b = (Prototype)a.clone();
		System.out.println(b.hashCode());
		b.setWke("02", "bbb");
		Prototype c = (Prototype)a.clone();
		System.out.println(c.hashCode());
		c.setWke("03", "ccc");
		System.out.println(a.toString());
		System.out.println(b.toString());
		System.out.println(c.toString());
	}
}

推荐写法(4):深克隆(通用)


创建Collection.java文件,具体内容如下:

package com.csdn.ingo.gof_prototype.four;

import java.io.Serializable;

public class Collection implements Serializable {
	private static final long serialVersionUID = 1L;
	private String date;
	private String company;

	public String getDate() {
		return date;
	}

	public void setDate(String date) {
		this.date = date;
	}

	public String getCompany() {
		return company;
	}

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

	@Override
	public Object clone() {
		Collection ca = null;
		try {
			ca = (Collection) super.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return ca;
	}

	@Override
	public String toString() {
		return "Collection [date=" + date + ", company=" + company + "]";
	}
}

创建Prototype.java文件,具体内容如下;

package com.csdn.ingo.gof_prototype.four;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class Prototype implements Serializable {

	private static final long serialVersionUID = 1L;
	private String name;
	private Collection work;

	public Prototype(String name) {
		this.name = name;
		work = new Collection();
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Collection getWork() {
		return work;
	}

	public void setWork(Collection work) {
		this.work = work;
	}

	public void setWke(String date, String company) {
		work.setDate(date);
		work.setCompany(company);
	}

	@Override
	public String toString() {
		return "Prototype [name=" + name + ", work=" + work.toString() + "]";
	}

	public Prototype clone() {
		ByteArrayOutputStream bao = new ByteArrayOutputStream();
		ObjectOutputStream oos;
		try {
			oos = new ObjectOutputStream(bao);
			oos.writeObject(this);

			ByteArrayInputStream bis = new ByteArrayInputStream(bao.toByteArray());
			ObjectInputStream ois;
			ois = new ObjectInputStream(bis);
			return (Prototype) ois.readObject();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}
}
创建Window.java文件,具体内容如下:

package com.csdn.ingo.gof_prototype.four;

public class Window {

	public static void main(String[] args) {
		Prototype a = new Prototype("ingo");
		System.out.println(a.hashCode());
		a.setWke("01", "aaa");
		Prototype b = (Prototype)a.clone();
		System.out.println(b.hashCode());
		b.setWke("02", "bbb");
		Prototype c = (Prototype)a.clone();
		System.out.println(c.hashCode());
		c.setWke("03", "ccc");
		System.out.println(a.toString());
		System.out.println(b.toString());
		System.out.println(c.toString());
	}
}<span style="font-family:Microsoft YaHei;font-size:14px;">
</span>

问题:浅克隆与深克隆的区别?

浅克隆:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用都仍然指向原来的对象。换句话说:对象成员变量中的简单类型都被复制,而引用对象类型,只复制引用,仍然指向原有对象,该对象仍然只有一份。

深克隆:被复制对象的所有变量都含有与原来的对象相同的值,所有的对其他对象的引用也复制一份引用的对象。换句话说:对象成员变量中的简单类型都被复制,而引用对象类型,不止复制引用,而是将引用对象也复制一份。

模式总结:

标准UML结构图:


概念总结:

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

组成部分:Prototype(原型类),ConcretePrototype(具体子类)两部分组成。

注:本文仅以Java为例说明,其他语言的原型模式,请各位看官自行学习。

反思:

应用场景:

  1. 创建相似的对象。
  2. 在上面的基础之上,创建新对象的花费资源较多,耗时较长的场景。
  3. 对象变化较小,并需要长时间保存时,在系统内创建备份时。
  4. 对象中含有组合属性,并且对象数量较少,考虑执行效率时。

优点:

  1. 当对象较为复杂,通过原型模式可以简化创建过程,提高创建效率。
  2. 扩展性好。客户端直接与抽象类进行交互,提高了双方的灵活性,扩展性。
  3. 提供深克隆,浅克隆两种方式供其使用。

缺点:

  1. 必须要为每一个对象创建一个克隆方法,克隆对象的任何改变,将直接违反“开闭原则”。
  2. 深克隆的过程需要IO等多个复杂过程。需要及时处理异常情况。
  3. 深层嵌套的克隆难于管理及实现。

-------------------------------------------------------------------------------------------------------------------------------------

至此,被说了很多遍的设计模式---原型模式 结束


参考资料:

图书:《大话设计模式》

其他博文:http://blog.csdn.NET/lovelion/article/details/7563445


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值