GOF23学习笔记(五)原型模式

原型模式

● 以某个对象为原型,复制出新的对象,显然,新的对象具有原型对象的所有特点

● 当通过new创建一个对象需要非常繁琐的数据准备或访问权限,则可以使用原型模式

● 优势:效率高,避免了重新执行构造过程步骤

● new创建出的对象属性值采用的是默认值,而克隆出的对象属性值与原型对象完全相同并且不会影响原型对象

原型模式的实现

  1. 原型类要实现Cloneable接口
  2. 实现clone()方法

浅克隆

原型类(Sheep.java)

public class Sheep implements Cloneable{
	private String name;
	private Date birthday;
	//重写Object类的clone()方法
	@Override
	protected Object clone() throws CloneNotSupportedException {
		Object obj = super.clone();
		return obj;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Date getBirthday() {
		return birthday;
	}
	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}
	public Sheep(String name, Date birthday) {
		super();
		this.name = name;
		this.birthday = birthday;
	}
	public Sheep() {
		super();
		// TODO Auto-generated constructor stub
	}
}

测试

public class Test {
	public static void main(String[] args) throws CloneNotSupportedException {
		Date date = new Date(123123123123L);
		Sheep s1 = new Sheep("少莉",date); //实例化原型对象
		System.out.println(s1);
		System.out.println(s1.getName());
		System.out.println(s1.getBirthday());

		Sheep s2 = (Sheep) s1.clone(); //调用clone()方法克隆出新对象
		
		System.out.println(s2);
		System.out.println(s2.getName());
		System.out.println(s2.getBirthday());
	}
}

由运行结果我们可以发现,虽然两个对象不是同一个对象,但他们的属性值是完全一样的


然后,我们修改新对象name属性值

可以看到只有新对象的值改变了,而原型对象没有改变

接下来,解释为什么这种方式称为浅克隆

在浅克隆中,原型对象中的成员变量是值类型,就复制一份给新对象;如果成员变量是引用类型,则将引用对象的地址复制给新对象。这样就会导致我们修改原型对象中引用类型变量的值,会导致克隆对象的值随之改变。



如何来解决这个问题呢,那就用深克隆来解决

深克隆有两种实现方式,一种是在clone()方法里添加代码,另一种是通过序列化与反序列化实现

添加代码的方式

原型类(sheep2.java)

public class Sheep2 implements Cloneable{
	private String name;
	private Date birthday;
	
	@Override
	protected Object clone() throws CloneNotSupportedException {
		Object obj = super.clone();
		
		//深克隆
		Sheep2 s = (Sheep2) obj;
		s.birthday = (Date) this.birthday.clone(); //把属性进行克隆
		
		return obj;
	}

	public String getName() {
		return name;
	}

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

	public Date getBirthday() {
		return birthday;
	}

	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}

	public Sheep2(String name, Date birthday) {
		super();
		this.name = name;
		this.birthday = birthday;
	}

	public Sheep2() {
		super();
		// TODO Auto-generated constructor stub
	}
}

测试,可以看到只有原型对象的值改变了,进行深克隆之后,相当于创建了一个新的引用对象,里面的值是一样的,并把克隆对象的成员变量指向它。



序列化和反序列化实现深克隆

猜你喜欢

转载自blog.csdn.net/IcyDate/article/details/80667056