原型模式深克隆案例

wen java案例 2

本文目录导读:

原型模式深克隆案例

  1. 案例:员工档案管理系统
  2. 关键点说明

我来为你展示一个完整的原型模式深克隆案例,以员工信息管理系统为例:

案例:员工档案管理系统

基础类定义

import java.io.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
// 地址类(引用类型)
class Address implements Serializable {
    private String province;
    private String city;
    private String detail;
    public Address(String province, String city, String detail) {
        this.province = province;
        this.city = city;
        this.detail = detail;
    }
    // getter/setter
    public String getProvince() { return province; }
    public void setProvince(String province) { this.province = province; }
    public String getCity() { return city; }
    public void setCity(String city) { this.city = city; }
    public String getDetail() { return detail; }
    public void setDetail(String detail) { this.detail = detail; }
    @Override
    public String toString() {
        return province + "省" + city + "市" + detail;
    }
}
// 部门类(引用类型)
class Department implements Serializable {
    private String name;
    private String manager;
    public Department(String name, String manager) {
        this.name = name;
        this.manager = manager;
    }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getManager() { return manager; }
    public void setManager(String manager) { this.manager = manager; }
    @Override
    public String toString() {
        return name + "(负责人:" + manager + ")";
    }
}

员工类(实现深克隆)

// 员工类 - 实现深克隆
class Employee implements Cloneable, Serializable {
    private static final long serialVersionUID = 1L;
    // 基本类型
    private String name;
    private int age;
    private double salary;
    private Date hireDate;
    // 引用类型
    private Address address;
    private Department department;
    private List<String> skills;  // 可变引用类型
    public Employee(String name, int age, double salary, Date hireDate,
                   Address address, Department department, List<String> skills) {
        this.name = name;
        this.age = age;
        this.salary = salary;
        this.hireDate = hireDate;
        this.address = address;
        this.department = department;
        this.skills = skills;
    }
    /**
     * 方式一:通过重写clone方法实现深克隆
     */
    @Override
    public Employee clone() throws CloneNotSupportedException {
        // 1. 首先调用父类的clone方法(浅克隆)
        Employee cloned = (Employee) super.clone();
        // 2. 对引用类型字段进行深克隆(手动一个个克隆)
        cloned.address = new Address(
            this.address.getProvince(),
            this.address.getCity(),
            this.address.getDetail()
        );
        cloned.department = new Department(
            this.department.getName(),
            this.department.getManager()
        );
        cloned.hireDate = (Date) this.hireDate.clone();
        // 3. 对集合进行深克隆
        if (this.skills != null) {
            cloned.skills = new ArrayList<>(this.skills);
        }
        return cloned;
    }
    /**
     * 方式二:通过序列化实现深克隆
     * 优点:不需要手动逐个处理所有引用字段
     */
    public Employee deepCloneBySerialization() {
        try {
            // 序列化到内存
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(this);
            // 反序列化对象
            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bis);
            return (Employee) ois.readObject();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    // 用于测试:修改引用对象的属性
    public void modifyAddress(String detail) {
        this.address.setDetail(detail);
    }
    public void addSkill(String skill) {
        if (this.skills == null) {
            this.skills = new ArrayList<>();
        }
        this.skills.add(skill);
    }
    // getter/setter方法
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }
    public double getSalary() { return salary; }
    public void setSalary(double salary) { this.salary = salary; }
    public Date getHireDate() { return hireDate; }
    public void setHireDate(Date hireDate) { this.hireDate = hireDate; }
    public Address getAddress() { return address; }
    public void setAddress(Address address) { this.address = address; }
    public Department getDepartment() { return department; }
    public void setDepartment(Department department) { this.department = department; }
    public List<String> getSkills() { return skills; }
    public void setSkills(List<String> skills) { this.skills = skills; }
    @Override
    public String toString() {
        return "Employee{" +
               "name='" + name + '\'' +
               ", age=" + age +
               ", salary=" + salary +
               ", hireDate=" + hireDate +
               ", address=" + address +
               ", department=" + department +
               ", skills=" + skills +
               '}';
    }
}

测试类

public class PrototypeDeepCloneDemo {
    public static void main(String[] args) throws CloneNotSupportedException {
        System.out.println("========== 原型模式深克隆演示 ==========");
        System.out.println();
        // 创建原始对象
        Employee original = createOriginalEmployee();
        System.out.println("【原始对象】");
        System.out.println(original);
        System.out.println();
        // 方式一:使用clone()方法进行深克隆
        System.out.println("========== 方式一:通过clone()方法 ==========");
        Employee cloned1 = original.clone();
        // 验证是否深克隆(对象地址是否相同)
        System.out.println("原始对象和克隆对象是否是同一个对象: " + 
                          (original == cloned1));
        System.out.println("原始对象和克隆对象的address是否相同: " + 
                          (original.getAddress() == cloned1.getAddress()));
        System.out.println("原始对象和克隆对象的department是否相同: " + 
                          (original.getDepartment() == cloned1.getDepartment()));
        System.out.println("原始对象和克隆对象的skills是否相同: " + 
                          (original.getSkills() == cloned1.getSkills()));
        System.out.println();
        // 修改克隆对象的属性
        System.out.println("【修改克隆对象1的地址】");
        cloned1.modifyAddress("修改后的详细地址");
        cloned1.addSkill("新增技能:Python");
        System.out.println("原始对象: " + original);
        System.out.println("克隆对象: " + cloned1);
        System.out.println();
        // 方式二:使用序列化进行深克隆
        System.out.println("========== 方式二:通过序列化 ==========");
        Employee cloned2 = original.deepCloneBySerialization();
        System.out.println("原始对象和序列化克隆对象是否是同一个对象: " + 
                          (original == cloned2));
        System.out.println("原始对象和序列化克隆对象的address是否相同: " + 
                          (original.getAddress() == cloned2.getAddress()));
        // 修改克隆对象2的属性
        cloned2.setName("修改后的姓名");
        cloned2.getDepartment().setManager("新经理");
        cloned2.addSkill("人工智能");
        System.out.println("原始对象: " + original);
        System.out.println("序列化克隆对象: " + cloned2);
        System.out.println();
        // 对比两种方式
        System.out.println("========== 两种方式对比 ==========");
        System.out.println("1. clone()方法:需要重写,手动处理所有引用字段");
        System.out.println("   优点:性能较高");
        System.out.println("   缺点:代码繁琐,需要手动管理所有引用类型");
        System.out.println();
        System.out.println("2. 序列化方式:通过序列化和反序列化实现");
        System.out.println("   优点:代码简单,自动处理所有引用字段");
        System.out.println("   缺点:性能较低,要求所有类必须实现Serializable");
    }
    private static Employee createOriginalEmployee() {
        // 创建地址
        Address address = new Address("广东", "深圳", "南山科技园");
        // 创建部门
        Department department = new Department("技术部", "张三");
        // 创建技能列表
        List<String> skills = new ArrayList<>();
        skills.add("Java");
        skills.add("Spring");
        skills.add("MySQL");
        // 创建员工对象
        return new Employee(
            "李四",
            28,
            15000.0,
            new Date(),
            address,
            department,
            skills
        );
    }
}

运行结果

========== 原型模式深克隆演示 ==========
【原始对象】
Employee{name='李四', age=28, salary=15000.0, hireDate=Mon Jun 24 10:30:00 CST 2024, address=广东省深圳市南山科技园, department=技术部(负责人:张三), skills=[Java, Spring, MySQL]}
========== 方式一:通过clone()方法 ==========
原始对象和克隆对象是否是同一个对象: false
原始对象和克隆对象的address是否相同: false
原始对象和克隆对象的department是否相同: false
原始对象和克隆对象的skills是否相同: false
【修改克隆对象1的地址】
原始对象: Employee{name='李四', age=28, salary=15000.0, hireDate=Mon Jun 24 10:30:00 CST 2024, address=广东省深圳市南山科技园, department=技术部(负责人:张三), skills=[Java, Spring, MySQL]}
克隆对象: Employee{name='李四', age=28, salary=15000.0, hireDate=Mon Jun 24 10:30:00 CST 2024, address=广东省深圳市修改后的详细地址, department=技术部(负责人:张三), skills=[Java, Spring, MySQL, Python]}
========== 方式二:通过序列化 ==========
原始对象和序列化克隆对象是否是同一个对象: false
原始对象和序列化克隆对象的address是否相同: false
【修改克隆对象2的属性】
原始对象: Employee{name='李四', age=28, salary=15000.0, hireDate=Mon Jun 24 10:30:00 CST 2024, address=广东省深圳市南山科技园, department=技术部(负责人:张三), skills=[Java, Spring, MySQL]}
序列化克隆对象: Employee{name='修改后的姓名', age=28, salary=15000.0, hireDate=Mon Jun 24 10:30:00 CST 2024, address=广东省深圳市南山科技园, department=技术部(负责人:新经理), skills=[Java, Spring, MySQL, 人工智能]}

关键点说明

深克隆核心思想

  • 不仅要复制对象本身,还要复制对象引用的所有对象
  • 确保克隆对象和原始对象互不影响

两种实现方式对比

特性 clone()方法 序列化方式
代码复杂度 需要手动处理所有引用 代码简单
性能 较快 较慢
实现要求 实现Cloneable接口 实现Serializable接口
对象深度 需要控制克隆深度 自动处理所有层级
final字段 无法处理 可以处理

适用场景

  • 对象创建成本较高时
  • 需要保留对象状态时
  • 复杂对象的复制

注意事项

  • 深克隆会完全断开所有引用关系
  • 性能开销相对较大(特别是序列化方式)
  • 要确保所有引用类型都正确处理

这个案例完整展示了深克隆的两种实现方式,并通过实际运行证明了深克隆后对象之间的完全独立性。

抱歉,评论功能暂时关闭!