java-设计模式(创建型)-【原型模式】

1.Prototype(原型模式)

   定义:用原型实例指定创建对象的种类,并且通过克隆这些原型创建新的对象。

   注意:这里的“克隆”,指的是通过调用Object类的clone方法来完成的,它直接在内存中复制数据

           因此不会调用到类的构造方法。不但构造方法中的代码不会执行,甚至连访问权限都对原型模式无效

   使用场景:

      原型模式本质上就是对象的拷贝,使用对象拷贝代替对象创建的原因有很多。比如对象的初始化构造非常复杂

      消耗资源巨大;运行时对象状态变化不可重现;无法获得对象的成员的运行时值

      使用原型模式创建对象比直接new一个对象在性能上要好的多,因为Object类的clone方法是一个本地方法,

      它直接操作内存中的二进制流,特别是复制大对象时,性能的差别非常明显。

   克隆满足的条件:

       clone()方法将对象复制了一份并返还给调用者。所谓“复制”的含义与clone()方法是怎么实现的。一般而言,clone()方法满足以下的描述:

  (1)对任何的对象x,都有:x.clone()!=x。换言之,克隆对象与原对象不是同一个对象。

  (2)对任何的对象x,都有:x.clone().getClass() == x.getClass(),换言之,克隆对象与原对象的类型一样。

  (3)如果对象x的equals()方法定义其恰当的话,那么x.clone().equals(x)应当成立的。

    在JAVA语言的API中,凡是提供了clone()方法的类,都满足上面的这些条件。JAVA语言的设计师在设计自己的clone()方法时,

        也应当遵守着三个条件。一般来说,上面的三个条件中的前两个是必需的,而第三个是可选的

   浅克隆和深克隆:

     浅复制:将一个对象复制后,基本数据类型的变量都会重新复制创建,而引用类型,指向的还是原对象所指向的。

     深复制:将一个对象复制后,不论是基本数据类型还有引用类型,都是重新创建的即引用类型的对象还会复制多一份。

               注意这里涉及到复制的深度问题,你要复制多深,即引用对象的深度。

2.原型模式与抽象工厂模式区别

      

    采用工厂模式:为每一个具体子类定义一个与其等级平行的工厂类,这样会变得重复累赘。

    采用原型模式:将对象本身当做工厂,通过clone方法克隆出自己的副本。

3.浅克隆和深克隆

/*
 * 一个原型类,只需要实现Cloneable接口,覆写clone方法,
 * 此处clone方法可以改成任意的名称,因为Cloneable接口是个空接口,
 * 你可以任意定义实现类的方法名,如cloneA或者cloneB,
 * 因为此处的重点是super.clone()这句话,super.clone()调用的是Object的clone()方法,
 * */
public class Prototype implements Cloneable {

	//浅复制:需要用public修饰符覆写clone方法
	public Object clone() throws CloneNotSupportedException 
	{
		Prototype proto=(Prototype)super.clone();
		return proto;
	}
	//深复制:将对象序列化入内存,再复制反序列化对象出来。
	public Object deepclone() throws IOException, ClassNotFoundException
	{
		//使用ByteArray输入输出流(节点流)写入内存(目的地)里,
		//使用Object输入输出流(处理流)将对象(源目标)写入。
		
		//写入当前对象的二进制流
		ByteArrayOutputStream bos=new ByteArrayOutputStream();//目的地
		ObjectOutputStream  oos=new ObjectOutputStream(bos);
		oos.writeObject(this);//源头写入
		
		//读取二进制流产生的新对象
		byte[] buf=new byte[1024];
		ByteArrayInputStream bis=new ByteArrayInputStream(bos.toByteArray());
		ObjectInputStream ois=new ObjectInputStream(bis);
		Prototype pro=(Prototype)ois.readObject();
		return pro;
	}
}

4.图解

   

  4.1 颜色原型及实现子类

//原型(接口)类,实现clonealbe接口
//指关心方法
public interface Prototype extends Cloneable{
    public Prototype clonenew()throws CloneNotSupportedException;
    public void display();
}
//颜色类,包含所有颜色,由初始化时定义该颜色和颜色值
class  ColorProto implements Prototype
{
    private String colorName;
    public String getColorName() {
		return colorName;
	}
	public void setColorName(String colorName) {
		this.colorName = colorName;
	}

	private int r;
    private int g;
    private int b;
	public ColorProto (String colorName,int r,int g,int b)
	{
		this.colorName=colorName;
		this.r=r;
		this.g=g;
		this.b=b;
	}
	//克隆自己
	@Override
	public ColorProto clonenew() throws CloneNotSupportedException {
		// TODO Auto-generated method stub
		ColorProto cp=(ColorProto) super.clone();
		return cp;
	}
    //显示自己的颜色名和值
	@Override
	public void display() {
		// TODO Auto-generated method stub
		System.out.println(colorName+":"+r+","+g+","+b);
	}
	
}

 4.2 颜色管理器

//管理颜色类,具有添加,取出颜色种类的方法
public class ColorProManage {

	private HashMap<String ,ColorProto> hm=new HashMap<String ,ColorProto>();
	
	//放入颜色
	public void putColor (ColorProto cp)
	{
		String colorName=cp.getColorName();
		hm.put(colorName, cp);
	}
	//取出颜色
	public ColorProto getColor(String colorName)
	{
		ColorProto cp=hm.get(colorName);
		if(cp!=null)
		return cp;
		else
			return null;
	}	
}

  4.3 测试

public class Test  {

	public static void main(String[] args) throws Exception {
		 
		 //新建颜色管理器
		 ColorProManage  cm=new ColorProManage();
		 //为颜色管理器添加颜色
		 ColorProto cp1=new ColorProto("red", 255, 0, 0);
		 ColorProto cp2=new ColorProto("green", 0, 255, 0);
		 ColorProto cp3=new ColorProto("blue",0, 0, 255);
		 cm.putColor(cp1);
		 cm.putColor(cp2);
		   cm.putColor(cp3);
		 //克隆出颜色管理器里的红色
		 ColorProto cpclone= cm.getColor("red").clonenew();
		 cpclone.display();
	} 
}

  4.4 运行结果

red:255,0,0

  

posted @ 2015-04-13 11:56  beyondbycyx  阅读(148)  评论(0编辑  收藏  举报