原型模式(prototype)

原型模式:

  • 通过new产生一个对象需要非常繁琐的数据准备或者访问权限,则可以使用原型模式。
  • 以摸个对象为原型,复制出新的对象,新对象具有原型对象的特点。
  • 优势:效率高(直接克隆,避免了重新执行构造过程步骤)
  • 克隆类似于new 但是不同于new .new 创建新的对象属性采用的是默认值,克隆出的对象属性值完全和原型对象相同,并且克隆出的新对象改变不会影响原型对象,然后再修改克隆对象的值。

原型模式的实现:

  • Cloneable接口和clone方法
  • Prototype模式中实现起来最困难的地方就是内存复制操作,提供clone()方法。

浅克隆实现

只是将原型对象的值全部克隆到复制对象,包括引用地址,所以两个指向同一引用,因此一个发生变化另外一个也会变化。
在这里插入图片描述

实体类:

public class Sheep implements Cloneable,Serializable {  
	private String sname;
	private Date birthday;
	
	
	@Override
	protected Object clone() throws CloneNotSupportedException {
		Object obj = super.clone();  //直接调用object对象的clone()方法!
		return obj;
	}


	public String getSname() {
		return sname;
	}


	public void setSname(String sname) {
		this.sname = sname;
	}


	public Date getBirthday() {
		return birthday;
	}


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


	public Sheep(String sname, Date birthday) {
		super();
		this.sname = sname;
		this.birthday = birthday;
	}
	
	public Sheep() {
	}
	
}

测试:

public class Client {
	public static void main(String[] args) throws Exception {
		Date date = new Date(12312321331L);
		Sheep s1 = new Sheep("1号羊",date);
		System.out.println(s1);
		System.out.println(s1.getSname());
		System.out.println(s1.getBirthday());
		
		System.out.println();
		
		Sheep s2 = (Sheep) s1.clone();
		//s2.setSname("2号羊");
		System.out.println(s2);
		System.out.println(s2.getSname());
		System.out.println(s2.getBirthday());
	}
}

结果:

com.feifan.prototype.Sheep@2a139a55
1号羊
Sat May 23 20:05:21 CST 1970

com.feifan.prototype.Sheep@70dea4e
1号羊
Sat May 23 20:05:21 CST 1970

深复制:

把对象下面的属性也进行克隆
在这里插入图片描述
实体类:

//测试深复制
public class Sheep2 implements Cloneable {   
	private String sname;
	private Date birthday;
	@Override
	protected Object clone() throws CloneNotSupportedException {
		Object obj = super.clone();  //直接调用object对象的clone()方法!
		//添加如下代码实现深复制(deep Clone)
		Sheep2 s = (Sheep2) obj;
		s.birthday = (Date) this.birthday.clone();  //把属性也进行克隆!
		return obj;
	}
	public String getSname() {
		return sname;
	}
	public void setSname(String sname) {
		this.sname = sname;
	}
	public Date getBirthday() {
		return birthday;
	}
	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}
	public Sheep2(String sname, Date birthday) {
		super();
		this.sname = sname;
		this.birthday = birthday;
	}
	public Sheep2() {
	}
}

测试:

public class Client2 {
	public static void main(String[] args) throws CloneNotSupportedException {
		Date date = new Date(12312321331L);
		Sheep2 s1 = new Sheep2("1号羊",date);
		Sheep2 s2 = (Sheep2) s1.clone();   //实现深复制。s2对象的birthday是一个新对象!
		
		System.out.println(s1);
		System.out.println(s1.getSname());
		System.out.println(s1.getBirthday());
		
		date.setTime(23432432423L);
		
		System.out.println(s1.getBirthday());
		System.out.println();
		
		s2.setSname("二号羊");
		System.out.println(s2);
		System.out.println(s2.getSname());
		System.out.println(s2.getBirthday());
	}
}

测试结果:

com.feifan.prototype.Sheep2@2a139a55
1号羊
Sat May 23 20:05:21 CST 1970
Tue Sep 29 13:00:32 CST 1970

com.feifan.prototype.Sheep2@70dea4e
2号羊
Sat May 23 20:05:21 CST 1970

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

实体类

public class Sheep implements Cloneable,Serializable {  
	private String sname;
	private Date birthday;
	@Override
	protected Object clone() throws CloneNotSupportedException {
		Object obj = super.clone();  //直接调用object对象的clone()方法!
		return obj;
	}
	public String getSname() {
		return sname;
	}
	public void setSname(String sname) {
		this.sname = sname;
	}
	public Date getBirthday() {
		return birthday;
	}
	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}
	public Sheep(String sname, Date birthday) {
		super();
		this.sname = sname;
		this.birthday = birthday;
	}
	public Sheep() {
	}
}

测试:

public class Client3 {
	public static void main(String[] args) throws CloneNotSupportedException, Exception {
		Date date = new Date(12312321331L);
		Sheep s1 = new Sheep("1号羊",date);
		System.out.println(s1);
		System.out.println(s1.getSname());
		System.out.println(s1.getBirthday());
		System.out.println();
		
//		使用序列化和反序列化实现深复制
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		ObjectOutputStream    oos = new ObjectOutputStream(bos);
		oos.writeObject(s1);
		byte[] bytes = bos.toByteArray();
		ByteArrayInputStream  bis = new ByteArrayInputStream(bytes);
		ObjectInputStream	  ois = new ObjectInputStream(bis);
		Sheep s2 = (Sheep) ois.readObject();   //克隆好的对象!
		System.out.println("修改原型对象的属性值");  
		date.setTime(23432432423L);
		System.out.println(s1.getBirthday());
		s2.setSname("2号羊");
		System.out.println(s2);
		System.out.println(s2.getSname());
		System.out.println(s2.getBirthday());
	}
}

测试结果:

com.feifan.prototype.Sheep@2a139a55
1号羊
Sat May 23 20:05:21 CST 1970

修改原型对象的属性值
Tue Sep 29 13:00:32 CST 1970
com.feifan.prototype.Sheep@677327b6
2号羊
Sat May 23 20:05:21 CST 1970


/**
 * @author Donald
 * @create 2019-07-14 21:23
 */
public class Prototype implements Cloneable, Serializable
{
    private static final long serialVersionUID = -3162496867309329422L;

    private String string;
    private SerializableObject obj;

    /* 浅复制 */
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return (Prototype)super.clone();
    }

    /* 深度复制*/
    public Object deepClone() throws IOException,ClassNotFoundException
    {
        /* 写入当前对象的二进制流 */
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(this);
        /* 读出二进制流产生的新对象 */
        ByteArrayInputStream bis = new ByteArrayInputStream( bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        return ois.readObject();
    }

    public String getString() {
        return string;
    }

    public void setString(String string) {
        this.string = string;
    }

    public SerializableObject getObj() {
        return obj;
    }

    public void setObj(SerializableObject obj) {
        this.obj = obj;
    }
}

class SerializableObject implements Serializable
{
    private static final long serialVersionUID = -3962008115218184619L;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值