原型模式

介绍

应用场景:原型模式就是从一个对象再创建另外一个可定制的对象,而且不需要知道任何创建的细节。
所谓原型模式,就是Java中的克隆技术,以某个对象为原型。复制出新的对象。显然新的对象具备原型对象的特点,效率高(避免了重新执行构造过程步骤)。
例子:孙悟空吹猴毛,变出N多个一样的猴子。

程序

package com.guo;

import java.util.ArrayList;

public class ConcretePrototype implements Cloneable{

	private int age;

	private String name;

	public ArrayList<String> list = new ArrayList<String>();

	protected Object clone() throws CloneNotSupportedException {
		ConcretePrototype prototype = null;
		try{
			prototype = (ConcretePrototype)super.clone();
			//prototype.list = (ArrayList)list.clone();

			//克隆基于字节码的
			//用反射,或者循环
		}catch(Exception e){

		}

		return prototype;
	}


	//定义上100个属性

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getName() {
		return name;
	}

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

	public ArrayList<String> getList() {
		return list;
	}

	public void setValue(String value) {
		this.list.add(value);
	}
}

ConcretePrototype cp = new ConcretePrototype();
		cp.setAge(18);
		cp.setName("Tom");

		cp.list.add("Tom");

		try {
			ConcretePrototype copy = (ConcretePrototype)cp.clone();
			copy.list.add("TOM1");
			System.out.println(copy.list  == cp.list);
			System.out.println(copy.getAge() + "," + copy.getName() + copy.list.size());
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}

运行结果:

通过观察,我们发现是浅拷贝。那怎么实现深拷贝呢。
可以通过两种思路考虑:1.是序列化和反序列化 2.反射
接下来列一下序列化和反序列化例子

//猴子
public class Monkey {
	//身高
	protected int height;//基本
	//体重
	protected int weight;
	//生日
	protected Date birthday;//不是基本类型

	public int getHeight() {
		return height;
	}
	public void setHeight(int height) {
		this.height = height;
	}
	public int getWeight() {
		return weight;
	}
	public void setWeight(int weight) {
		this.weight = weight;
	}
	public Date getBirthday() {
		return birthday;
	}
	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}
	
}
/**
 * 金箍棒
 * @author Tom
 *
 */
public class GoldRingedStaff implements Serializable{

	private float height = 100; //长度
	private float diameter = 10;//直径


	/**
	 * 金箍棒长大
	 */
	public void grow(){
		this.diameter *= 2;
		this.height *= 2;
	}

	/**
	 * 金箍棒缩小
	 */
	public void shrink(){
		this.diameter /= 2;
		this.height /= 2;
	}

}

public class TheGreatestSage  extends Monkey implements Cloneable,Serializable{

	//金箍棒
	private GoldRingedStaff staff;

	//从石头缝里蹦出来
	public TheGreatestSage(){
		this.staff = new GoldRingedStaff();
		this.birthday = new Date();
		this.height = 150;
		this.weight = 30;
	}

	//分身技能
	public Object clone(){
		//深度克隆
		ByteArrayOutputStream bos = null;
		ObjectOutputStream oos = null;
		ByteArrayInputStream bis = null;
		ObjectInputStream ois = null;
		try {
			//return super.clone();//默认浅克隆,只克隆八大基本数据类型和String
			//序列化
			bos = new ByteArrayOutputStream();
			oos = new ObjectOutputStream(bos);
			oos.writeObject(this);

			//反序列化
			bis = new ByteArrayInputStream(bos.toByteArray());
			ois = new ObjectInputStream(bis);
			TheGreatestSage copy = (TheGreatestSage)ois.readObject();
			copy.birthday = new Date();

			return copy;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}finally{
			try {
				bos.close();
				oos.close();
				bis.close();
				ois.close();

			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	//变化
	public void change(){
		TheGreatestSage copySage = (TheGreatestSage)clone();
		System.out.println("大圣本尊生日是:" + this.getBirthday().getTime());
		System.out.println("克隆大圣的生日是:" + copySage.getBirthday().getTime());
		System.out.println("大圣本尊和克隆大圣是否为同一个对象:" + (this == copySage));
		System.out.println("大圣本尊持有的金箍棒跟克隆大圣持有金箍棒是否为同一个对象:" + (this.getStaff() == copySage.getStaff()));
	}

	public GoldRingedStaff getStaff() {
		return staff;
	}

	public void setStaff(GoldRingedStaff staff) {
		this.staff = staff;
	}
	
}

测试下:

TheGreatestSage sage = new TheGreatestSage();
		sage.change();

结果:

posted @ 2019-04-18 16:06  梅溪梦窗  阅读(61)  评论(0)    收藏  举报