设计模式之原型设计模式,对象拷贝

1.原型设计模式之浅拷贝

  • 原型设计模式prototype

    • 是一种对象创建型模式,使用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象,主要用于创建重复的对象,同时又能保证性能
    • 工作原理:将一个原型对象传给那个要发动创建的对象,这个要发动创建的对象通过请求原型对象拷贝自己来实现创建过程
    • 最简单的设计模式,实现一个接口Cloneable,重写clone()方法即完成原型模式
  • 核心组成

    • Prototype:声明克隆方法的接口,是所有具体原型类的公共父类,Cloneable接口
    • ConcretePrototype:具体原型类
    • Client:让一个原型对象克隆自身从而创建一个新的对象
  • 应用场景

    • 创建新对象成本较大,新的对象可以通过原型模式对已有对象进行复制来获得
    • 如果系统要保存对象的状态,做备份使用
  • 浅拷贝代码示例

    import java.util.ArrayList;
    import java.util.List;
    
    class Person implements Cloneable {
        private String name;
        private List<String> list = new ArrayList<>();
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public List<String> getList() {
            return list;
        }
    
        public void setList(List<String> list) {
            this.list = list;
        }
    
        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", list=" + list +
                    '}';
        }
    
        @Override
        protected Person clone() throws CloneNotSupportedException {
            return (Person) super.clone();
        }
    }
    
    public class Main {
        public static void main(String[] args) throws CloneNotSupportedException {
            Person zhangsan = new Person();
            zhangsan.setName("zhangsan");
            zhangsan.getList().add("aaa");
            System.out.println(zhangsan);
    
            Person zhangsan2 = zhangsan.clone();
            System.out.println(zhangsan2);
    
            zhangsan2.setName("zhangsan2");
            zhangsan2.getList().add("ccc");
            System.out.println(zhangsan);
            System.out.println(zhangsan2);
        }
    }
    

2.原型设计模式之深拷贝

  • 浅拷贝遗留问题

    • 通过对一个类进行实例化来构造新对象,不同的是,原型模式是通过拷贝一个现有对象生成新对象
    • 浅拷贝实现Cloneable,深拷贝通过实现Serializable读取二进制流
  • 浅拷贝

    • 如果原型对象的成员变量是基本数据类型(int、double、byte、boolean、char等),将复制一份给克隆对象
    • 如果原型对象的成员变量是引用类型,则将引用对象的地址复制一份给克隆对象,也就是说原型对象和克隆对象的成员变量指向相同的内存地址
    • 通过重写Object类的clone()方法可以实现浅克隆
  • 深拷贝

    • 无论原型对象的成员变量是基本数据类型还是引用类型,都将复制一份给克隆对象,如果需要实现深克隆,可以通过序列化(Serializable)等方式来实现
  • 原型模式是内存二进制流的拷贝,比new对象性能高很多,使用的时候记得注意是选择浅拷贝还是深拷贝

  • 优点

    • 当创建新的对象实例较为复杂时,使用原型模式可以简化对象的创建过程,可以提高新实例的创建效率
    • 可辅助实现撤销操作,使用深克隆的方式保存对象的状态,使用原型模式将对象复制一份并将其状态保存起来,以便在需要的时候使用恢复到历史状态
  • 缺点

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

    import java.io.*;
    import java.util.ArrayList;
    import java.util.List;
    
    class Person implements Cloneable, Serializable {
        private String name;
        private List<String> list = new ArrayList<>();
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public List<String> getList() {
            return list;
        }
    
        public void setList(List<String> list) {
            this.list = list;
        }
    
        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", list=" + list +
                    '}';
        }
    
        @Override
        protected Person clone() throws CloneNotSupportedException {
            return (Person) super.clone();
        }
    
        /**
         * 深拷贝
         *
         * @return
         */
        public Person deepClone() {
            try {
                // 输出 序列化
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                ObjectOutputStream outputStream = new ObjectOutputStream(byteArrayOutputStream);
                outputStream.writeObject(this);
                // 输入 反序列化
                ObjectInputStream inputStream = new ObjectInputStream(new ByteArrayInputStream(byteArrayOutputStream.toByteArray()));
                Person copyObj = (Person) inputStream.readObject();
                return copyObj;
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    }
    
    public class Main {
        public static void main(String[] args) throws CloneNotSupportedException {
            Person zhangsan = new Person();
            zhangsan.setName("zhangsan");
            zhangsan.getList().add("aaa");
            System.out.println(zhangsan);
    
            Person zhangsan2 = zhangsan.deepClone();
            System.out.println(zhangsan2);
    
            zhangsan2.setName("zhangsan2");
            zhangsan2.getList().add("ccc");
            System.out.println(zhangsan);
            System.out.println(zhangsan2);
        }
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Gen邓艮艮

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值