[设计模式] - 原型模式 拔一根毫毛吹出猴万个

原型模式(Prototype Pattern)是 创建型模式 的一种,其特点在于通过“复制”一个已经存在的实例来返回新的实例,而不是新建实例。被复制的实例就是我们所称的“原型”,这个原型是可定制的。

适用场景

  1. 类初始化消耗资源较多
  2. new产生的对象需要比较繁琐的过程
  3. 构造函数比较复杂
  4. 循环体内产生大量的对象

简单克隆

创建基础ConcretePrototype,它实现了Prototypeclone()

public class ConcretePrototype implements Prototype {

    private int age;
    private List hobbis;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public List getHobbis() {
        return hobbis;
    }

    public void setHobbis(List hobbis) {
        this.hobbis = hobbis;
    }

    @Override
    public Prototype clone() {
        ConcretePrototype concretePrototype = new ConcretePrototype();
        concretePrototype.setAge(this.age);
        concretePrototype.setHobbis(this.hobbis);
        return concretePrototype;
    }
}

创建测试类,查看复制结果。

public class Test {
    public static void main(String[] args) {
        ConcretePrototype concretePrototype = new ConcretePrototype();
        concretePrototype.setAge(15);
        List<String> list = new ArrayList<>();
        concretePrototype.setHobbis(list);
        ConcretePrototype concretePrototype1 = (ConcretePrototype) concretePrototype.clone();

        System.out.println("克隆对象引用地址"+(concretePrototype == concretePrototype1));
        System.out.println("克隆属性引用地址"+(concretePrototype.getHobbis() == concretePrototype1.getHobbis()));
    }
}


可以看出,我们确实复制了一个新的类。但是hobbies的应用地址却是相同的,意味着我们复制的并不是值,而是引用的地址。这就是我们常说的浅克隆

浅克隆
复制出来的对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。
深克隆
复制出来的所有变量都含有与原来的对象相同的值,那些引用其他对象的变量将指向复制出来的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。

深克隆实现版


我们使用孙悟空的作为模型。猴哥猴哥,你真了不得,拔一根毫毛吹出猴万个,但是每只猴子都有个金箍棒,而这个金箍棒的复制应该就属于深克隆。接下来我们实现一下。
首先创建一个可序列化的金箍棒

public class Jingubang implements Serializable {

    public float h = 100;
    public float d = 10;
}

再创建一个悟空

public class Wukong implements Cloneable, Serializable {
    private int height;
    private int weight;
    private Jingubang jingubang;

    public Wukong() {
        this.height = 1;
        this.weight = 1;
        this.jingubang = new Jingubang();
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }

    public Jingubang getJingubang() {
        return jingubang;
    }

    public void setJingubang(Jingubang jingubang) {
        this.jingubang = jingubang;
    }

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

    public Wukong deepClone(){

        try {
            ByteOutputStream byteOutputStream = new ByteOutputStream();
            ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteOutputStream);
            objectOutputStream.writeObject(this);

            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteOutputStream.toByteArray());
            ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);

            Wukong copy = (Wukong) objectInputStream.readObject();
            return copy;

        } catch (IOException e) {
            e.printStackTrace();
            return null;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            return null;
        }
    }
}

使用序列化复制生成实例。

public class WukongTest {
    public static void main(String[] args) {
        Wukong sunweukong = new Wukong();

        Wukong liuermihou = null;
        try {
            liuermihou = (Wukong) sunweukong.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        System.out.println(sunweukong.getJingubang());
        System.out.println(liuermihou.getJingubang());
        System.out.println("克隆对象引用地址"+(sunweukong == liuermihou));
        System.out.println("克隆属性引用地址"+(sunweukong.getJingubang() == liuermihou.getJingubang()));

    }
}


由测试可以看出,我们复制生成的实例,已经完全是全新的实例了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值