Java设计模式-11 、原型模式

原型模式

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

原型模式实际上就是实现 Cloneable 接口,重写 clone()方法。

使用原型模式的优点:

● 性能优良 原型模式是在内存二进制流的拷贝,要比直接 new 一个对象性能好很多,特别是 要在一个循环体内产生大量的对象时,原型模式可以更好地体现其优点。

● 逃避构造函数的约束 这既是它的优点也是缺点,直接在内存中拷贝,构造函数是不会执行的

使用场景:

● 资源优化场景 类初始化需要消化非常多的资源,这个资源包括数据、硬件资源等。

● 性能和安全要求的场景 通过 new 产生一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模 式。

● 一个对象多个修改者的场景 一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以 考虑使用原型模式拷贝多个对象供调用者使用。

浅拷贝和深拷贝:

浅拷贝:Object 类提供的方法 clone 只是拷贝本对象,其对象内部的数组、引用 对象等都不拷贝,还是指向原生对象的内部元素地址,这种拷贝就叫做浅拷贝,其 他的原始类型比如 int、long、char、string(当做是原始类型)等都会被拷贝。 注意: 使用原型模式时,引用的成员变量必须满足两个条件才不会被拷贝:一是 类的成员变量,而不是方法内变量;二是必须是一个可变的引用对象,而不是一个 原始类型或不可变对象。

深拷贝:对私有的类变量进行独立的拷贝 如:thing.arrayList = (ArrayList)this.arrayList.clone();  

 代码:

1. 实体对象

public class NewPrototype implements Cloneable {
	private String id;

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	private Prototype prototype;

	public Prototype getPrototype() {
		return prototype;
	}

	public void setPrototype(Prototype prototype) {
		this.prototype = prototype;
	}

	public Object clone() {
		try {
			return super.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
			return null;
		}
	}
}
/**
 * 深复制
 * 
 * @author WHM
 *
 */
public class NewPrototypes implements Cloneable {
	private String id;

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	private Prototypes prototype;

	public Prototypes getPrototype() {
		return prototype;
	}

	public void setPrototype(Prototypes prototype) {
		this.prototype = prototype;
	}

	public Object clone() {
		NewPrototypes ret = null;
		try {
			ret = (NewPrototypes) super.clone();
			ret.prototype = (Prototypes) this.prototype.clone();
			return ret;
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
			return null;
		}
	}
}
public class Prototype {
	//引用类型
	private String name;
	 
	 public String getName() {
	  return name;
	 }
	 
	 public void setName(String name) {
	  this.name = name;
	 } 
}
public class Prototypes implements Cloneable {
	private String name;

	public String getName() {
		return name;
	}

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

	public Object clone() {
		try {
			return super.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
			return null;
		}
	}
}
import java.io.Serializable;

public class PrototypeSe implements Serializable {
	 private String name;
	 
	 public String getName() {
	  return name;
	 }
	 
	 public void setName(String name) {
	  this.name = name;
	 }
}
/**
 * 序列化实现深复制
 * 
 * @author WHM
 *
 */
public class NewPrototypeSe implements Serializable {
	private String id;

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	private PrototypeSe prototype;

	public PrototypeSe getPrototype() {
		return prototype;
	}

	public void setPrototype(PrototypeSe prototype) {
		this.prototype = prototype;
	}

	public Object deepClone() {
		ByteArrayOutputStream bo = null;
		ObjectOutputStream oo = null;
		ByteArrayInputStream bi = null;
		ObjectInputStream oi = null;
		try {
			bo = new ByteArrayOutputStream();
			oo = new ObjectOutputStream(bo);
			oo.writeObject(this);

			bi = new ByteArrayInputStream(bo.toByteArray());
			oi = new ObjectInputStream(bi);
			return oi.readObject();
		} catch (IOException | ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		} finally {
				try {
					if(bo != null) {
					bo.close();
					}
				} catch (IOException e) {
					e.printStackTrace();
				}
				try {
					if(oo != null) {
						oo.close();
					}
				} catch (IOException e) {
					e.printStackTrace();
				}
				try {
					if(bi != null) {
						bi.close();
					}
				} catch (IOException e) {
					e.printStackTrace();
				}
				try {
					if(oi != null) {
						oi.close();
					}
				} catch (IOException e) {
					e.printStackTrace();
				}
		}
	}
}

2 验证

package pattern.prototype;

import java.io.IOException;

/**
 * 原型模式(Prototype pattern)是指原型实例指定创建对象的种类,并且通过复制这些原型创建新的对象。原型模式主要适用于以下:
  (1)类初始化消耗资源较多;
  (2)使用new 生成一个对象需要非常繁琐的过程(数据准备访问权限等);
  (3)构造函数比较复杂;
  (4)在循环体中产生大量对象;
  在spring中用到的原型模式有:scope="prototype" ,还有常用的JSON.parseObject()也是一种原型模式
 * @author WHM
 * 
 * 2.在Java中对象的克隆有深克隆和浅克隆之分。
 * 有这种区分的原因是Java中分为基本数据类型和引用数据类型
 * ,对于不同的数据类型在内存中的存储的区域是不同的。基本数据类型存储在栈中,引用数据类型存储在堆中。
 *
 * 2.1浅克隆
        只复制基本类型的数据,引用类型的数据只复制了引用的地址,引用的对象并没有复制,在新的对象中修改引用类型的数据会影响原对象中的引用
   2.2复制后的对象与原对象之间完全不会影响。
 */
public class TMain {

	public static void main(String[] args) throws Exception {
		
		/**
		 * 浅复制
		 */

		  Prototype pro = new Prototype(); pro.setName("original object"); NewPrototype
		  newObj = new NewPrototype(); newObj.setId("test1"); newObj.setPrototype(pro);

		  NewPrototype copyObj = (NewPrototype)newObj.clone();
		  copyObj.setId("testCopy"); //String对象值会变化
		  copyObj.getPrototype().setName("changed object");

		  System.out.println("original object id:" + newObj.getId());
		  System.out.println("original object name:" +
		  newObj.getPrototype().getName());

		  System.out.println("cloned object id:" + copyObj.getId());
		  System.out.println("cloned object name:" + copyObj.getPrototype().getName());

		  /**
		   * 深复制
		   */

//		  Prototypes pro = new Prototypes(); pro.setName("original object");
//		  NewPrototypes newObj = new NewPrototypes(); newObj.setId("test1");
//		  newObj.setPrototype(pro);
//
//		  NewPrototypes copyObj = (NewPrototypes)newObj.clone();
//		  copyObj.setId("testCopy"); copyObj.getPrototype().setName("changed object");
//
//		  System.out.println("original object id:" + newObj.getId());
//		  System.out.println("original object name:" +
//		  newObj.getPrototype().getName()); //2个全新的对象
//		  System.out.println("cloned object id:" + copyObj.getId());
//		 System.out.println("cloned object name:" + copyObj.getPrototype().getName());
//
		  /**
		   * 3.深复制by Serializable
		   */
		  // TODO Auto-generated method stub
		  PrototypeSe po = new PrototypeSe();
		  po.setName("test1");
		  NewPrototypeSe se = new NewPrototypeSe();
		  se.setPrototype(po);
		  
		  NewPrototypeSe deepClone = (NewPrototypeSe)se.deepClone();
		  deepClone.getPrototype().setName("test2");
		  
		  System.out.println("original name:" + se.getPrototype().getName());
		  System.out.println("cloned name:" + deepClone.getPrototype().getName());
	}
}

3. 结果

 

 

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值