原型设计模式 与 深拷贝 浅拷贝

简介

原型模式(prototype) java中有一个克隆技术,以某个对象为原型,复制出新的对象。使用克隆,类似于new,但是又不同于new。这是从内存中直接复制了,使用克隆,有效率高的优点,避免了重新执行构造过程的步骤。


原型模式的实现

我们可以想象一下以下一些场景:
火影忍者中,鸣人查克拉的分生。
西游记中,孙悟空把一根毛变出一堆孙悟空。

这些情况出来的人,都不是一个一个从婴儿长大的,高效地一会儿就就能在短时间内产出。
即使是现实中的克隆羊多利,其实生命的成长也比普通羊快上不少。(据说因为他是克隆的6岁的羊,多利一生出来就是6岁,具体不知 (^__^) …)


  • 在prototype模式中 我们首先要cloneable接口实现clone方法,clone方法是在object类里面的,会自动从object类中继承
public class Prototype implements Cloneable{
    private String sname;
    private Date  birthday;

    @Override
    protected Object clone() throws CloneNotSupportedException {
        //掉用 object 的克隆方法
        return super.clone();
    }

    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 Prototype(String sname, Date birthday) {
        super();
        this.sname = sname;
        this.birthday = birthday;
    }

}

  • 下面我们定义一个 客户类用于测试
/**
 * 原型方法的测试
 * @author guxiang
 * @date 2017-2-25 上午10:09:27
 */
public class Client {
    public static void main(String[] args) throws Exception {
        Prototype p1 = new Prototype("二狗",new Date());

        Prototype p2 = (Prototype) p1.clone();
        System.out.println(p1);
        System.out.println(p1.getSname());
        System.out.println(p1.getBirthday());
        System.out.println("--------------");
        System.out.println(p2);
        System.out.println(p2.getSname());
        System.out.println(p2.getBirthday());

    }
}


----------
执行结果如下

com.guxiang.prototype.Prototype@6af62373
二狗
Sat Feb 25 11:26:56 CST 2017
--------------
com.guxiang.prototype.Prototype@12276af2
二狗
Sat Feb 25 11:26:56 CST 2017

在执行结果中,我们可以看到, 对象的hash值(内存地址)是不一样的,代表他们两个不是一个对象,然而对象里面属性的值 都是一样的,相当于一个克隆人,他不是你,然而属性和外表都一样

  • 上面我们讲的其实是一种浅拷贝
  • -

什么是浅拷贝呢?

public class Client {
    public static void main(String[] args) throws Exception {
        Date date = new Date();
        Prototype p1 = new Prototype("二狗",date);
        System.out.println(p1);
        System.out.println(p1.getSname());
        System.out.println(p1.getBirthday());


        Prototype p2 = (Prototype) p1.clone();
        date.setTime(1235);
        System.out.println("--------------");
        System.out.println(p2);
        System.out.println(p2.getSname());
        System.out.println(p2.getBirthday());

    }
}
----------
执行结果如下
com.guxiang.prototype.Prototype@6af62373
二狗
Sat Feb 25 11:50:54 CST 2017
--------------
com.guxiang.prototype.Prototype@12276af2
二狗
Thu Jan 01 08:00:01 CST 1970

我们可以看出,如果原型依赖于另外一个对象,那么clone的时候,浅拷贝只是拷贝了原型所依赖的对象的地址,而没有吧原型所依赖的对象拷贝进去。

这里写图片描述


那么怎么在原型模式中使用深拷贝呢?


我只需要在克隆的时候 把属性也克隆。

public class Prototype implements Cloneable{
    private String sname;
    private Date  birthday;


    /**
     * 深拷贝的代码实现
     */
    @Override
    protected Object clone() throws CloneNotSupportedException {
        //掉用 object 的克隆方法
        Object object = super.clone();

        Prototype prototype = (Prototype) object;
         prototype.birthday = (Date) this.birthday.clone();

        return prototype;
    }

    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 Prototype(String sname, Date birthday) {
        super();
        this.sname = sname;
        this.birthday = birthday;
    }

}

深拷贝将原型所依赖的对象 也拷贝了一份
内存图如下
这里写图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值