原型模式

原型模式

用原型对象,拷贝,创建新的对象。
就是复制。咦惹。

拷贝出的对象只是属性相同,对象可不是同一个对象,这点很容易理解。

原型模式的优点是在对象属性增加或减少时方便

案例:克隆羊

现在有一只羊,名为tom,年龄为1岁,颜色为白色。请根据Tom属性编写程序创建与根据Tom属性完全相同的10只羊。
思考:羊类class Sheep属性name age color

public class Test {
	public static void main(String[] args) {
		//一般方法
		Sheep sheep=new Sheep("tom",1,"白色");
		
		new Sheep(sheep.getName(),sheep.getAge(),sheep.getColor());
		new Sheep(sheep.getName(),sheep.getAge(),sheep.getColor());
		new Sheep(sheep.getName(),sheep.getAge(),sheep.getColor());
		new Sheep(sheep.getName(),sheep.getAge(),sheep.getColor());
		new Sheep(sheep.getName(),sheep.getAge(),sheep.getColor());
		new Sheep(sheep.getName(),sheep.getAge(),sheep.getColor());
		new Sheep(sheep.getName(),sheep.getAge(),sheep.getColor());
		new Sheep(sheep.getName(),sheep.getAge(),sheep.getColor());
		new Sheep(sheep.getName(),sheep.getAge(),sheep.getColor());
		new Sheep(sheep.getName(),sheep.getAge(),sheep.getColor());//烦
	}
}

class Sheep{
	private String name;
	private int age;
	private String color;
	public Sheep() {
		super();
	}
	public Sheep(String name, int age, String color) {
		super();
		this.name = name;
		this.age = age;
		this.color = color;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getColor() {
		return color;
	}
	public void setColor(String color) {
		this.color = color;
	}
	@Override
	public String toString() {
		return "Sheep [name=" + name + ", age=" + age + ", color=" + color + "]";
	}

}

原型模式的核心操作

Java中Object类中提供了clone方法,该方法可以将一个对象复制一份,但是该对象的类得实现接口Cloneable。默认为浅拷贝

使用原型模式进行操作

public class Test1 {
	public static void main(String[] args) throws CloneNotSupportedException {
		Sheep sheep=new Sheep("tom",1,"白色");
		Sheep sheep1=(Sheep) sheep.clone();
		Sheep sheep2=(Sheep)sheep.clone();
		Sheep sheep3=(Sheep)sheep.clone();
		Sheep sheep4=(Sheep)sheep.clone();
		Sheep sheep5=(Sheep)sheep.clone();
		Sheep sheep6=(Sheep)sheep.clone();
		Sheep sheep7=(Sheep)sheep.clone();
		Sheep sheep8=(Sheep)sheep.clone();
		Sheep sheep9=(Sheep)sheep.clone();
		Sheep sheep10=(Sheep)sheep.clone();//实际上还是烦的,不懂原型模式的意义在哪。据说有更高的效率。
		System.out.println(sheep);
		System.out.println(sheep1);
		System.out.println(sheep2);
		System.out.println(sheep3);
		System.out.println(sheep4);
		System.out.println(sheep5);
		System.out.println(sheep6);
		System.out.println(sheep7);
		System.out.println(sheep8);
		System.out.println(sheep9);
		System.out.println(sheep10);
		
	}

}

class Sheep implements Cloneable{
	private String name;
	private int age;
	private String color;
	public Sheep() {
		super();
	}
	public Sheep(String name, int age, String color) {
		super();
		this.name = name;
		this.age = age;
		this.color = color;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getColor() {
		return color;
	}
	public void setColor(String color) {
		this.color = color;
	}
	@Override
	public String toString() {
		return "Sheep [name=" + name + ", age=" + age + ", color=" + color + "]";
	}
	
	//重写Cloneable中的clone方法
	@Override
	protected Object clone() throws CloneNotSupportedException {
		Sheep sheep=null;
		sheep=(Sheep) super.clone();
		return sheep;
	}
}

Spring中的bean的创建,就使用了原型模式。

原型模式中的浅拷贝

羊中有属性a,这个属性a有指针指向B对象
克隆羊属性a,这个属性a的有的指针也指向B对象

经测试不同sheep的friend的地址值相同且属性相同,说明为同一个friend。

即不同羊的friend为同一个friend
这里的对象是排除基本数据类型和字符串数据类型的

public class Test2 {
	public static void main(String[] args) throws CloneNotSupportedException {
		Sheep sheep=new Sheep("tom",1,"白色");
		sheep.friend=new Sheep("jack",2,"黑色");
		
		Sheep sheep1=(Sheep) sheep.clone();
		Sheep sheep2=(Sheep)sheep.clone();
		Sheep sheep3=(Sheep)sheep.clone();
		
		System.out.println("sheep="+sheep+"sheep.frend="+sheep.friend.hashCode());
		System.out.println("sheep1="+sheep1+"sheep1.frend="+sheep1.friend.hashCode());
		System.out.println("sheep2="+sheep2+"sheep2.frend="+sheep2.friend.hashCode());
		System.out.println("sheep3="+sheep3+"sheep3.frend="+sheep3.friend.hashCode());
		
		/*
		 * 结果: sheep=Sheep [name=tom, age=1, color=白色]sheep.frend=366712642
				sheep1=Sheep [name=tom, age=1, color=白色]sheep1.frend=366712642
				sheep2=Sheep [name=tom, age=1, color=白色]sheep2.frend=366712642
				sheep3=Sheep [name=tom, age=1, color=白色]sheep3.frend=366712642
				把它们的friend地址值打出来如下,是相同的。
				test2.Sheep@6d06d69c
				test2.Sheep@6d06d69c
				test2.Sheep@6d06d69c
				test2.Sheep@6d06d69c
				
		 */
		//也就是说Sheep中的属性friend对象,在其他克隆羊中friend都是同一对象,称此为浅拷贝。
		//这里的friend就类似于它的指针被克隆羊复制了,所有指针指向同一对象。
	}

}

class Sheep implements Cloneable{
	private String name;
	private int age;
	private String color;
	public Sheep friend;//friend是对象。
	public Sheep() {
		super();
	}
	public Sheep(String name, int age, String color) {
		super();
		this.name = name;
		this.age = age;
		this.color = color;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getColor() {
		return color;
	}
	public void setColor(String color) {
		this.color = color;
	}
	@Override
	public String toString() {
		return "Sheep [name=" + name + ", age=" + age + ", color=" + color + "]";
	}
	
	//重写Cloneable中的clone方法
	@Override
	protected Object clone() throws CloneNotSupportedException {
		Sheep sheep=null;
		sheep=(Sheep) super.clone();
		return sheep;
	}
}

原型模式中的深拷贝

羊中有属性a,这个属性a有指针指向B对象
克隆羊属性a,这个属性a的有的指针指向B对象的克隆

经测试不同sheep的friend的地址值不同但属性相同,说明不是同一个friend。

即不同羊的friend为不同的friend
这里的对象是排除基本数据类型和字符串数据类型的

对此案例深拷贝,用静态方法

public class Test3 {
	public static void main(String[] args) throws CloneNotSupportedException {
		Sheep sheep=new Sheep("tom",1,"白色");
		sheep.friend=new Sheep("jack",2,"黑色");
		
		Sheep sheep1=Sheep.friendClone((Sheep)sheep.clone());
		Sheep sheep2=Sheep.friendClone((Sheep)sheep.clone());
		Sheep sheep3=Sheep.friendClone((Sheep)sheep.clone());
		
		System.out.println("sheep="+sheep+"sheep.frend="+sheep.friend.hashCode());
		System.out.println("sheep1="+sheep1+"sheep1.frend="+sheep1.friend.hashCode());
		System.out.println("sheep2="+sheep2+"sheep2.frend="+sheep2.friend.hashCode());
		System.out.println("sheep3="+sheep3+"sheep3.frend="+sheep3.friend.hashCode());
		
		System.out.println(sheep.friend);//fiend 中的属性还是相同的
		System.out.println(sheep1.friend);
		System.out.println(sheep2.friend);
		System.out.println(sheep3.friend);
		
		System.out.println(sheep1.friend.friend);
		
		/*结果(此结果为测试结果而非固定代码结果)
		 * Sheep的friend属性 [name=jack, age=2, color=黑色]
			Sheep1的friend属性[name=jack, age=2, color=黑色]
			Sheep2的friend属性 [name=jack, age=2, color=黑色]
			Sheep3的friend属性 [name=jack, age=2, color=黑色]
			
		 * sheep=test3.Sheep@15db9742sheep.frend=1829164700
		 * sheep1=test3.Sheep@7852e922sheep1.frend=1311053135
		 * sheep2=test3.Sheep@70dea4esheep2.frend=1550089733
		 * sheep3=test3.Sheep@33909752sheep3.frend=1442407170 
		 * test3.Sheep@6d06d69c	sheep的friend的地址
		 * test3.Sheep@4e25154f	sheep1的friend的地址
		 * test3.Sheep@5c647e05	sheep2的friend的地址
		 * test3.Sheep@55f96302 sheep3的sheep的friend的地址
		 * null   sheep1.friend.friend的地址值
		 * 
		 * 说明不同sheep的friend的属性相同但地址值不同,即friend对象不是同一个。
		 */

		
	}

}

class Sheep implements Cloneable{
	private String name;
	private int age;
	private String color;
	public Sheep friend;//friend是对象。
	public Sheep() {
		super();
	}
	public Sheep(String name, int age, String color) {
		super();
		this.name = name;
		this.age = age;
		this.color = color;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getColor() {
		return color;
	}
	public void setColor(String color) {
		this.color = color;
	}
	@Override
	public String toString() {
		return "Sheep [name=" + name + ", age=" + age + ", color=" + color + "]";
	}
	
	//重写Cloneable中的clone方法
	@Override
	protected Object clone() throws CloneNotSupportedException {
		Sheep sheep=null;
		sheep=(Sheep) super.clone();
		return sheep;
	}
	
	public static Sheep friendClone(Sheep sheep) throws CloneNotSupportedException {
		sheep.friend=(Sheep) sheep.friend.clone();
		return sheep;
	}
}

深拷贝的实现方式一:重写clone方法

此方式思路与上面的静态思路相同

public class Test {
	public static void main(String[] args) throws CloneNotSupportedException {
		DeepProtoType deepProtoType=new DeepProtoType();
		deepProtoType.name="宋江";
		deepProtoType.deepCloneableTarget=new DeepCloneableTarget("大牛", "大牛的类");
		
		//深拷贝
		DeepProtoType deepProtoType2=(DeepProtoType) deepProtoType.clone();
		
		System.out.println(deepProtoType);
		System.out.println(deepProtoType2);
		/*
		 * DeepProtoType [name=宋江,deepCloneableTarget=test.DeepCloneableTarget@15db9742]
		 *  DeepProtoType[name=宋江, deepCloneableTarget=test.DeepCloneableTarget@6d06d69c]
		 *  
		 */
		System.out.println(deepProtoType.deepCloneableTarget);
		System.out.println(deepProtoType2.deepCloneableTarget);
//		DeepCloneableTarget [cloneName=大牛, cloneClass=大牛的类]
//		DeepCloneableTarget [cloneName=大牛, cloneClass=大牛的类]
	}
}

//实现Serializable,Cloneable接口
class DeepCloneableTarget implements Serializable, Cloneable {
	private static final long serialVersionUID = 1L;// 这个是啥?

	private String cloneName;
	private String cloneClass;

	public DeepCloneableTarget(String cloneName, String cloneClass) {
		this.cloneName = cloneName;
		this.cloneClass = cloneClass;
	}

	@Override
	protected Object clone() throws CloneNotSupportedException {
		return super.clone();
	}

	@Override
	public String toString() {
		return "DeepCloneableTarget [cloneName=" + cloneName + ", cloneClass=" + cloneClass + "]";
	}
	
	
}

class DeepProtoType implements Serializable, Cloneable {
	public String name;
	public DeepCloneableTarget deepCloneableTarget;

	public DeepProtoType() {
	}

	// 完成深拷贝实现,重写clone方法
	@Override
	protected Object clone() throws CloneNotSupportedException {
		Object deep = null;
		// 这里完成对基本数据类型和String类型的复制
		deep = super.clone();
		// 这里对剩余类型进行处理
		DeepProtoType deepProtoType = (DeepProtoType) deep;
		deepProtoType.deepCloneableTarget = (DeepCloneableTarget) deepCloneableTarget.clone();
		return deepProtoType;
	}

	@Override
	public String toString() {
		return "DeepProtoType [name=" + name + ", deepCloneableTarget=" + deepCloneableTarget + "]";
	}

}

深拷贝的实现方式二:通过对象序列化(推荐)

public class Test1 {
	public static void main(String[] args) throws CloneNotSupportedException, ClassNotFoundException {
		DeepProtoType deepProtoType=new DeepProtoType();
		deepProtoType.name="宋江";
		deepProtoType.deepCloneableTarget=new DeepCloneableTarget("大牛", "大牛的类");
		
		DeepProtoType deepProtoType2=(DeepProtoType) deepProtoType.deepClone();
		System.out.println(deepProtoType);
		System.out.println(deepProtoType2);
		
//		DeepProtoType [name=宋江, deepCloneableTarget=test1.DeepCloneableTarget@3d4eac69]
//		DeepProtoType [name=宋江, deepCloneableTarget=test1.DeepCloneableTarget@214c265e]
		
		System.out.println(deepProtoType.deepCloneableTarget);
		System.out.println(deepProtoType2.deepCloneableTarget);
		
//		DeepCloneableTarget [cloneName=大牛, cloneClass=大牛的类]
//		DeepCloneableTarget [cloneName=大牛, cloneClass=大牛的类]
	}

}

//实现Serializable,Cloneable接口
class DeepCloneableTarget implements Serializable, Cloneable {
	private static final long serialVersionUID = 1L;// 这个是啥?

	private String cloneName;
	private String cloneClass;

	public DeepCloneableTarget(String cloneName, String cloneClass) {
		this.cloneName = cloneName;
		this.cloneClass = cloneClass;
	}

	@Override
	protected Object clone() throws CloneNotSupportedException {
		return super.clone();
	}

	@Override
	public String toString() {
		return "DeepCloneableTarget [cloneName=" + cloneName + ", cloneClass=" + cloneClass + "]";
	}

}

class DeepProtoType implements Serializable, Cloneable {
	public String name;
	public DeepCloneableTarget deepCloneableTarget;

	public DeepProtoType() {
	}

	@Override
	public String toString() {
		return "DeepProtoType [name=" + name + ", deepCloneableTarget=" + deepCloneableTarget + "]";
	}

	// 序列化核心
	public Object deepClone() throws ClassNotFoundException {
		// 创建流对象
		ByteArrayOutputStream bos = null;
		ObjectOutputStream oos = null;
		ByteArrayInputStream bis = null;
		ObjectInputStream ois = null;

		try {
			// 序列化操作
			bos = new ByteArrayOutputStream();
			oos = new ObjectOutputStream(bos);
			oos.writeObject(this);//当前这个对象以对象流的方式输出。
			
			//反序列化
			bis=new ByteArrayInputStream(bos.toByteArray());
			ois=new ObjectInputStream(bis);
				DeepProtoType copyObj=(DeepProtoType) ois.readObject();
				return copyObj;
			
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		}finally {
			//关闭流
			try {
				bos.close();
				oos.close();
				bis.close();
				ois.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
	}

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值