原型模式

介绍


原型模式就是对象的copy。在堆中已经有了对象,我们通过克隆的方式复制一份一模一样的对象出来,这就是原型模式。因为只是内存的copy问题, 这样的话省去了创建一个对象的时间。与new不同的地方就是,通过new的方式创建的对象属性采用的是默认值。克隆出来的对象属性值完全和原型对象相同,并且克隆出来的对象发生变化一般不会影响原型对象。

实现方式


实现Cloneable接口和clone方法

示例


  • 示例一

实现Cloneable接口(其实不用真的实现,这里只是给编译器一个暗示,说明该类可以被克隆)。重写clone方法,该方法是Object中的方法,涉及到内存copy,我们只需要调用父类的clone方法即可。

package com.dy.xidian;

import java.util.Date;

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

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

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

    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;
    }

}

 测试类

package com.dy.xidian;

import java.sql.Date;

public class Clinet {

    public static void main(String[] args) throws CloneNotSupportedException {
        Sheep s1 = new Sheep("羊", new Date(123456789L));
        // 打印原羊的信息
        System.out.println("----原羊-----");
        System.out.println(s1);
        System.out.println(s1.getSname());
        System.out.println(s1.getBirthday());

        // clone出一个新对象
        Sheep s2 = (Sheep) s1.clone();
        // 打印克隆羊信息
        System.out.println("------克隆羊------");
        System.out.println(s2);
        System.out.println(s2.getSname());
        System.out.println(s2.getBirthday());
        // 更改克隆羊属性
        s2.setSname("克隆羊");
        s2.setBirthday(new Date(1234565433L));
        System.out.println("-----对比------");
        System.out.println("原羊:" + s1.getSname());
        System.out.println("克隆羊:" + s2.getSname());
        System.out.println("克隆羊:" + s2.getBirthday());
    }

}

 

  • 示例二
package com.dy.xidian;

import java.sql.Date;

public class Clinet {

    public static void main(String[] args) throws CloneNotSupportedException {
        Date d = new Date(123456789L);
        Sheep s1 = new Sheep("羊", d);
        // 打印原羊的信息
        System.out.println("----原羊-----");
        System.out.println(s1);
        System.out.println(s1.getSname());
        System.out.println(s1.getBirthday());

        // clone出一个新对象
        Sheep s2 = (Sheep) s1.clone();
        // 打印克隆羊信息
        System.out.println("------克隆羊------");
        System.out.println(s2);
        System.out.println(s2.getSname());
        System.out.println(s2.getBirthday());
        // 更改原羊属性
        d.setDate(123456789);
        System.out.println("-----对比------");
        System.out.println("原羊:" + s1.getBirthday());
        System.out.println("克隆羊:" + s2.getBirthday());
    }

}

 

 

可以发现当我们修改了data的值后原型和克隆的对象的值都同时发生了变化。这是因为在clone的时候,属性是完全copy。原羊的birtyday属性指向d对象,那么copy出来的birthday属性也应指向相同的对象。当d对象发生改变的时候,这两个属性的值都发生了变化。这就是所谓的浅copy。

深克隆技术


 

深克隆需要对属性也进行克隆

package com.dy.xidian;

import java.util.Date;

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

    @Override
    protected Object clone() throws CloneNotSupportedException {
        Sheep s = (Sheep) super.clone();
        s.birthday = (Date) this.birthday.clone();
        return s;
    }

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

    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;
    }
}

 

通过反序列化实现深克隆

package com.dy.xidian;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.sql.Date;

public class Clinet {

    public static void main(String[] args) throws CloneNotSupportedException,
            IOException, ClassNotFoundException {
        Date d = new Date(123456789L);
        Sheep s1 = new Sheep("羊", d);
        // 打印原羊的信息
        System.out.println("----原羊-----");
        System.out.println(s1);
        System.out.println(s1.getSname());
        System.out.println(s1.getBirthday());

        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("----克隆羊-----");
        System.out.println(s2);
        System.out.println(s2.getSname());
        System.out.println(s2.getBirthday());

        d.setDate(1784567658);
        System.out.println("------对比------");
        System.out.println("原羊: " + s1.getBirthday());
        System.out.println("克隆羊: " + s2.getBirthday());
    }

}

posted @ 2016-06-29 16:36  被罚站的树  阅读(170)  评论(0编辑  收藏  举报