创建型之原型模式

2020-12-15  本文已影响0人  FisherTige_f2ef

原型模式(Prototype Pattern)

不需要经过构造函数创建实例,直接在内存中拷贝对象实例,常用于为了创建重复的对象,又要保证较高性能的场景。

优点: 1、性能提高。 2、逃避构造函数的约束。

缺点:如果复制的对象 里面又有引用其他对象,然后引用的其他对象再有其他对象的引用(有很多层),需要考虑以下问题:1、复制需要深入多少层。2、如何避免出现循环引用的问题

使用场景: 1、资源优化场景,对于一个已存在内存中的类实例,需要创建多个实例提供给其他对象访问,而且各个调用者可能都需要修改其值时,但是类初始化需要消化非常多的资源,这个资源包括硬件资源、非常繁琐的数据准备或访问权限等,可以考虑使用原型模式拷贝多个对象供调用者使用。

 java最常见的原型模式实现就是深拷贝与浅拷贝。

浅拷贝

在内存层面对一个对象进行拷贝,对象有着原始对象基本类型数据的一份精确拷贝,及引用类型的内存地址拷贝。即如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址。因此,如果其中一个对象改变了这个地址,就会影响到另一个对象。

实现方式:重写Clone方法

public class ShallowClone implements Cloneable {

            public int a;  // 基本类型

            public int[]b; // 非基本类型

            // 重写Object.clone()方法,并把protected改为public

            @Override

            public Objectclone(){

                        ShadowClone sc =null;

                        try{

                                sc = (ShallowClone)super.clone();

                        }catch (CloneNotSupportedException e){

                                e.printStackTrace();

                        }

                return sc;

        }

}

深拷贝

在内存层面对一个对象进行拷贝,对象有着原始对象基本类型数据的一份精确拷贝,及引用类型的内存地址指向的内存数据。即如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址指向的内存数据。因此,如果其中一个对象改变了这个地址,不会影响到另一个对象。

实现方式:

1、重写Clone方法

class Bottle implements Cloneable {

    public Wine wn;

    public Bottle(Wine wn){

        this.wn = wn;

    }

    // 覆写clone()方法

    @Override

    protected Object clone() throws CloneNotSupportedException{

        Bottle newBtl = (Bottle)super.clone();

        newBtl.wn = (Wine) wn.clone();

        return newBtl;

    }

}

class Wine implements Cloneable {

    int degree;

    public int getDegree() {

        return degree;

    }

    public void setDegree(int degree){

        this.degree = degree;

    }

    // 覆写clone()方法

    @Override

    protected Object clone() throws CloneNotSupportedException{

        return super.clone();

    }

}

2、采用序列化方式,例如serializable、 Parcelable、ProtoBuf等

class DeepPerson implements Serializable {

    private int a;

    private int[] b;

    public DeepPerson(){

    }

    public DeepPerson(int a, int[] b){

        this.a = a;

        this.b = b;

    }

    public int getA(){

        return a;

    }

    public void setA(int a){

        this.a = a;

    }

    public int[] getB(){

        return b;

    }

    public void setB(int[] b){

        this.b = b;

    }

}

public static void main(String[] args) throws CloneNotSupportedException{

        DeepPerson dc1 = new DeepPerson();

        // 对dc1赋值

        dc1.setA(100);

        dc1.setB(new int[]{ 1000 });

        System.out.println("克隆前dc1: a=" + dc1.getA()+"b[0]=" + dc1.getB()[0]);

        DeepPerson dc2 = (DeepPerson) deepClone(dc1);

        // 对c2进行修改

        dc2.setA(50);

        int[] a = dc2.getB();

        a[0] =500;

        System.out.println("克隆后dc1: a=" + dc1.getA()+"b[0]=" + dc1.getB()[0]);

        System.out.println("克隆后dc2: a=" + dc2.getA()+"b[0]=" + dc2.getB()[0]);

    }

public static Object deepClone(Objectobject){

        Object o=null;

        try{

            if (object !=null){

                ByteArrayOutputStream baos = new ByteArrayOutputStream();

                ObjectOutputStream oos = new ObjectOutputStream(baos);

                oos.writeObject(object);

                oos.close();

                ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());

                ObjectInputStream ois = new ObjectInputStream(bais);

                o = ois.readObject();

                ois.close();

            }

        } catch (IOException e){

                e.printStackTrace();

        } catch (ClassNotFoundException e) {

                e.printStackTrace();

        }

        return o;

        }

}

上一篇下一篇

猜你喜欢

热点阅读