深度揭秘原型(深浅克隆)模式!

来源:互联网 发布:淘宝企业店铺装修教程 编辑:程序博客网 时间:2024/05/17 07:34

原型模式:
原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

深克隆和浅克隆:
1、对于浅克隆

public class People implements Cloneable {    String name;    int age;    Date date;    public Date getDate() {        return date;    }    public void setDate(Date date) {        this.date = date;    }    public People(String name, int age, Date date) {        super();        this.name = name;        this.age = age;        this.date = date;    }    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;    }    @Override    public String toString() {        return "People [name=" + name + ", age=" + age + ", date=" + date + "]";    }    public People() {        super();    }    public People(String name, int age) {        super();        this.name = name;        this.age = age;    }    @Override    protected Object clone() throws CloneNotSupportedException {        return super.clone();    }}

测试类:

public class Client {    public static void main(String[] args) throws Exception {        Date date = new Date(2364262352L);        System.out.println(date);        People p1 = new People("张三", 18,date);        date.setTime(62786892498243L);        System.out.println(date);        People p2 = (People) p1.clone();        System.out.println(p1);        System.out.println(p2);        System.out.println(p1.hashCode() +"-----"+p2.hashCode());        /*         * 打印结果:         *          * People [name=张三, age=18, date=Sat Aug 22 11:28:18 GMT+08:00 3959]         * People [name=张三, age=18, date=Sat Aug 22 11:28:18 GMT+08:00 3959]         *发现:克隆之后在修改时间依然还是没有变化。         * */    }}

对于浅克隆,如图所示:
这里写图片描述

深克隆:
这里有两种方式:
1、通过重写clone方法,来实现深克隆。

/** * 深度克隆 * */public class People2 implements Cloneable {    String name;    int age;    Date date;    public Date getDate() {        return date;    }    public void setDate(Date date) {        this.date = date;    }    public People2(String name, int age, Date date) {        super();        this.name = name;        this.age = age;        this.date = date;    }    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;    }    @Override    public String toString() {        return "People [name=" + name + ", age=" + age + ", date=" + date + "]";    }    public People2() {        super();    }    public People2(String name, int age) {        super();        this.name = name;        this.age = age;    }    @Override    protected People2 clone() throws CloneNotSupportedException {        //在克隆对象的同时把对象的属性也给克隆了        Object obj = super.clone();        People2 p = (People2) obj;        Date d = (Date) p.date.clone();        p.setDate(d);        return p;    }}

测试代码:

public class Client2 {    public static void main(String[] args) throws CloneNotSupportedException {        Date date = new Date(2678264781672L);        People2 p = new People2("张三",12,date);        People2 p1 = p.clone();        date.setTime(897892798732L);        System.out.println(p);        System.out.println(p1);        /*         * 打印结果:         * People [name=张三, age=12, date=Mon Jun 15 14:39:58 GMT+08:00 1998]         *  People [name=张三, age=12, date=Sat Nov 14 18:26:21 GMT+08:00 2054]         * 可以观察到深度克隆之后,在修改属性此时就会发生变化         * */    }}

第二种方式,通过序列化和反序列化来实现:

public class People3 implements Serializable {    private static final long serialVersionUID = 1L;    String name;    Date date;    @Override    public String toString() {        return "People3 [name=" + name + ", date=" + date + "]";    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public Date getDate() {        return date;    }    public void setDate(Date date) {        this.date = date;    }    public People3(String name, Date date) {        super();        this.name = name;        this.date = date;    }    public People3() {        super();        // TODO Auto-generated constructor stub    }    //内容写到数组里边然后在读取 , 通过此种方式来深度复制对象    public People3 clone(People3 p){        //定义这个数组用于接收对象信息        byte[] by=null;        //初始化字节数组输出流        ByteArrayOutputStream baos = null;        //初始化对象输出流        ObjectOutputStream oos = null;        try {            baos = new ByteArrayOutputStream();            oos = new ObjectOutputStream(baos);            //将对象写入到硬盘中            oos.writeObject(p);            by = baos.toByteArray();        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }finally{            try {                if (oos != null) {                    oos.close();                }            } catch (IOException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        }        //获取字节数组输入流        ByteArrayInputStream bais = null;        //获得对象输入六        ObjectInputStream ois = null;        try {            //读取by数组            bais = new ByteArrayInputStream(by);            ois = new ObjectInputStream(bais);            //通过反序列化读取到对象            People3 p1= (People3) ois.readObject();            //System.out.println(p);            return p1;        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        } catch (ClassNotFoundException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }finally{            try {                bais.close();            } catch (IOException e1) {                // TODO Auto-generated catch block                e1.printStackTrace();            }            try {                if (ois != null) {                    ois.close();                }            } catch (IOException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        }        return null;    }}

测试代码:

public class Client3 {    public static void main(String[] args) {        Date d = new Date(35483782375L);        System.out.println(d);        People3 p = new People3("张三",d);        People3 p1 = p.clone(p);        d.setTime(78946582782L);        System.out.println("p的时间"+"---"+d);        System.out.println("p"+"---"+p);        System.out.println("p1"+"---"+p1);        /*         * 打印结果:         *  Tue Feb 16 00:36:22 GMT+08:00 1971         *  p的时间---Mon Jul 03 01:36:22 GMT+08:00 1972         *  p---People3 [name=张三, date=Mon Jul 03 01:36:22 GMT+08:00 1972]         *  p1---People3 [name=张三, date=Tue Feb 16 00:36:22 GMT+08:00 1971]         *         * 如上一种深克隆一样         * */    }}

那么,原型模式到底在什么时候用?
假设一个系统的产品类是动态加载的,而且产品类具有一定的等级结构。这个时候如果采取工厂模式的话,工厂类就不得不具有一个相应的等级结构。而产品品类的等级结构一旦变化,工厂类的等级结构就不得不有以恶相应的变化。这对于产品结构可能会有经常变化的系统来说,采用工厂模式就有不方便之处。
此时若采用原型模式,给每一个产品类配备一个克隆方法(大多时候只需个产品类等级结构配备一个根类配备一个克隆方法),便可免去工厂模式所带来的据哟有固定等级结构的工厂类。

还有一点,假设通过普通方法创建对象很耗时时,也可采用原型模式,例如:

/** * 测试普通new方式创建对象和clone方式创建对象的效率差异! * 如果需要短时间创建大量对象,并且new的过程比较耗时。则可以考虑使用原型模式! *  * */public class Client4 {    public static void testNew(int size){        long start = System.currentTimeMillis();        for(int i=0;i<size;i++){            Laptop t = new Laptop();        }        long end = System.currentTimeMillis();        System.out.println("new的方式创建耗时:"+(end-start));    }    public static void testClone(int size) throws CloneNotSupportedException{        long start = System.currentTimeMillis();        Laptop t = new Laptop();        for(int i=0;i<size;i++){            Laptop temp = (Laptop) t.clone();        }        long end = System.currentTimeMillis();        System.out.println("clone的方式创建耗时:"+(end-start));    }    public static void main(String[] args) throws Exception {           testNew(1000);        testClone(1000);        /**         * 测试结果:         * new的方式创建耗时:10288         *  clone的方式创建耗时:10         *         *          * */    }}class Laptop implements Cloneable {  //笔记本电脑    public Laptop() {        try {            Thread.sleep(10);  //模拟创建对象耗时的过程!        } catch (InterruptedException e) {            e.printStackTrace();        }    }    @Override    protected Object clone() throws CloneNotSupportedException {        Object obj = super.clone();  //直接调用object对象的clone()方法!        return obj;    }}
原创粉丝点击