当前位置: 首页 > news >正文

深克隆和浅克隆(建造者模式,内含简版)

让我们来看一个例子:

设计一个客户类Customer,其中客户地址存储在地址类Address中,用浅克隆和深克隆分别实现Customer对象的复制并比较这两种克隆方式的异同。

代码实现

Customer类和Address类都是实现的Java 内置的 java.lang.Cloneable 接口,无需自己定义

1. ​Customer 类

package experiment05.二;

public class Customer implements Cloneable {
    private String name;
    private int age;
    private Address address;

    // 构造方法接受 CustomerBuilder 参数
    public Customer(CustomerBuilder builder) {
        this.name = builder.getName();
        this.age = builder.getAge();
        this.address = builder.getAddress();
    }

    // 浅克隆
    @Override
    public Customer clone() throws CloneNotSupportedException {
        return (Customer) super.clone();
    }

    // 深克隆
    public Customer deepClone() throws CloneNotSupportedException {
        Customer cloned = (Customer) super.clone();
        cloned.address = this.address.clone();
        return cloned;
    }

    // Getter 方法
    public Address getAddress() {
        return address;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

2. ​CustomerBuilder 类

package experiment05.二;

public class CustomerBuilder {
    private String name;
    private int age;
    private Address address;

    public CustomerBuilder withName(String name) {
        this.name = name;
        return this;
    }

    public CustomerBuilder withAge(int age) {
        this.age = age;
        return this;
    }

    public CustomerBuilder withAddress(Address address) {
        this.address = address;
        return this;
    }

    public Customer build() {
        return new Customer(this);
    }

    // 提供给 Customer 构造方法访问的 Getter
    String getName() {
        return name;
    }

    int getAge() {
        return age;
    }

    Address getAddress() {
        return address;
    }
}

3.Address 类

package experiment05.二;

public class Address implements Cloneable {
    private String street;
    private String city;

    public Address(String street, String city) {
        this.street = street;
        this.city = city;
    }

    @Override
    public Address clone() throws CloneNotSupportedException {
        return (Address) super.clone();
    }

    public void setStreet(String street) {
        this.street = street;
    }

    public String getStreet() {
        return street;
    }

    public String getCity() {
        return city;
    }
}

4. ​Main 类

package experiment05.二;

public class Main {
    public static void main(String[] args) throws CloneNotSupportedException {
        // 使用独立建造者类创建对象(链式写法)
        Customer original = new CustomerBuilder()
                .withName("张三")
                .withAge(30)
                .withAddress(new Address("人民路123号", "北京市"))
                //以上三个的编译类型和运行类型都是CustomerBuilder
                .build();
                // 只有这个返回的是Customer对象(Customer的编译运行类型),build()方法实际返回的是new Customer(...)对象
        /**
         * 编译类型由变量声明或方法返回类型决定
         * 运行类型由实际创建的对象决定
         */
        
        /*     ==等效于==
        步骤1:创建建造者对象
        CustomerBuilder builder1 = new CustomerBuilder(); // ✅ 编译类型=运行类型=CustomerBuilder
        步骤2:设置姓名(返回建造者)
        CustomerBuilder builder2 = builder1.withName("张三"); // ✅ 编译类型=运行类型=CustomerBuilder
        步骤3:设置年龄(返回建造者)
        CustomerBuilder builder3 = builder2.withAge(30); // ✅ 编译类型=运行类型=CustomerBuilder
        步骤4:设置地址(返回建造者)
        CustomerBuilder builder4 = builder3.withAddress(new Address("人民路123号", "北京市")); // ✅ 类型同上
        步骤5:构建最终对象
        Customer original = builder4.build(); // ✅ 编译类型=Customer | 运行类型=Customer
         */
        // 浅克隆和深克隆
        Customer shallowCopy = original.clone();
        Customer deepCopy = original.deepClone();

        // 修改原对象地址
        original.getAddress().setStreet("长安街456号");

        // 验证结果
        System.out.println("原始对象地址: " + original.getAddress().getStreet());      // 长安街456号
        System.out.println("浅克隆对象地址: " + shallowCopy.getAddress().getStreet()); // 长安街456号
        System.out.println("深克隆对象地址: " + deepCopy.getAddress().getStreet());    // 人民路123号
    }
}

简单版 (无建造者)

class Address implements Cloneable {
    private String street;
    private String city;

    public Address(String street, String city) {
        this.street = street;
        this.city = city;
    }

    @Override
    public Address clone() throws CloneNotSupportedException {
        return (Address) super.clone();
    }

    public void setStreet(String street) {
        this.street = street;
    }

    public String getStreet() {
        return street;
    }
}

class Customer implements Cloneable {
    private String name;
    private int age;
    private Address address;

    // 直接使用构造方法初始化
    public Customer(String name, int age, Address address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }

    // 浅克隆
    @Override
    public Customer clone() throws CloneNotSupportedException {
        return (Customer) super.clone();
    }

    // 深克隆
    public Customer deepClone() throws CloneNotSupportedException {
        Customer cloned = (Customer) super.clone();
        cloned.address = this.address.clone();
        return cloned;
    }

    public Address getAddress() {
        return address;
    }

    public String getName() {
        return name;
    }
}

public class Main {
    public static void main(String[] args) throws CloneNotSupportedException {
        // 直接使用构造方法创建对象
        Customer original = new Customer("张三", 30, new Address("人民路123号", "北京市"));
        
        Customer shallowCopy = original.clone();
        Customer deepCopy = original.deepClone();

        original.getAddress().setStreet("长安街456号");

        System.out.println("原始对象地址: " + original.getAddress().getStreet());     // 长安街456号
        System.out.println("浅克隆对象地址: " + shallowCopy.getAddress().getStreet()); // 长安街456号
        System.out.println("深克隆对象地址: " + deepCopy.getAddress().getStreet());    // 人民路123号
    }
}

相关文章:

  • 解码未来:DeepSeek开源FlashMLA,推理加速核心技术,引领AI变革
  • 低功耗可编程RTU在热网监控中的应用
  • 抽象工厂设计模式及应用案例
  • 如何在阿里云linux主机上部署Node.Js
  • ADB介绍
  • 《C语言数据类型取值范围:一场数字的“极限挑战”之旅》
  • CSS 中opacity属性和rgba颜色表示法中透明度的区别及应用场景
  • Kubernetes高级应用之-重启策略
  • 【数据库发展史】
  • 文章记单词 | 第2篇(六级)
  • 3.23[A]linux
  • 量子计算在密码学中的应用:机遇与挑战并存
  • MySQL InnoDB行锁等待时间是怎么引起的?
  • 对象的创建
  • 进程通信(进程池的模拟实现) read write函数复习 Linux ─── 第23课
  • 数据库基础知识点(系列四)
  • OpenCV图像拼接(7)根据权重图对源图像进行归一化处理函数normalizeUsingWeightMap()
  • SQL 通用表表达式(CTE )
  • Linux之基本命令和格式
  • RabbitMQ 学习整理2 - 消峰限流
  • 排名好的锦州网站建设/360优化大师
  • 深圳建设银行网站/2345网址导航主页
  • 做搜索网站挣钱/网页seo搜索引擎优化
  • dreamweaver的优点/抖音seo排名软件哪个好
  • 江门网站制作培训/2023推广平台
  • 免费自助建站工具/福州关键词搜索排名