设计模式(创建型)---原型模式

概述

原型模式的定义:以一个已经创建的实例作为原型,通过复制该对象来创建一个和原型相同或相似的新对象。

优点

1.复制在性能上比直接 new 一个对象更加优良。
2.可以使用深拷贝方式保存对象的状态,使用原型模式将对象复制一份,并将其状态保存起来,可辅助实现撤销操作。

缺点

1.需要为每一个类配备一个克隆方法,对已有的类进行改造时,需要修改源代码,违背了“开闭原则”
2.在实现深克隆时需要编写较为复杂的代码,且当对象之间存在多重的嵌套引用时,需要对每一层对象对应的类都必须支持深克隆

应用场景

当创建新对象成本较高时或需要创建大量相同或相似的对象时

举例说明

一个类实现Coneable接口,重写clone方法即完成了一个最简单的原型模式

public class Student implements Cloneable{

    private int age;

    private String name;

    public int getAge() {
        return age;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

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

测试,debug看一下student1与student2的区别
在这里插入图片描述
可以看到student1与student2两个对象的name字段的内存地址是一样的,也就是两个对象引用了同一个name字段,这是因为实现cloneable接口属于浅拷贝

深拷贝与浅拷贝的区别

浅拷贝:如果原型对象的成员变量是基本数据类型(int、double、byte、boolean、char等),将复制一份给克隆对象;
如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,也就是说原型对象和克隆对象的成员变量指向相同的内存地址,通过覆盖Object类的clone()方法可以实现浅克隆
深拷贝:无论原型对象的成员变量是基本数据类型还是引用类型,都将复制一份给克隆对象,如果需要实现深克隆,可以通过序列化(Serializable)等方式来实现
原型模式是内存二进制流的拷贝,比new对象性能高很多
要实现深拷贝,要实现序列化接口Serializable
代码如下

public class Student implements Cloneable, Serializable{

    private int age;

    private String name;

    public int getAge() {
        return age;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

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

    /**
     * 深拷贝
     * @return
     * @throws IOException
     */
    public Student deepClone() throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(this);

        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bais);
        try {
            Student copy = (Student) ois.readObject();
            return copy;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            return null;
        }
    }

}

测试
在这里插入图片描述
name属性地址不同,两个对象都有属于自己的name字段,实现了深拷贝

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值