六.原型模式

一.原型模式的定义

原型模式是一种创建型设计模式,通过复制现有对象(原型)生成新对象,避免重复初始化成本。需了解以下关键概念:

  • 浅拷贝‌:复制基本类型字段,引用类型字段共享内存地址(修改新对象会影响原对象)。
  • 深拷贝‌:递归复制引用对象(如通过序列化/手动复制),新旧对象完全独立。

二.实现方式

2.1. Java 原生实现(了解)

实现Cloneable接口,声明对象可以被克隆。Cloneable接口是个空接口,有仅有标志作用

通过Object的clone()方法复制现有对象生成新实例,而非通过构造函数创建,默认是浅拷贝。

也可以深拷贝,但是需要手动赋值,且需处理异常,本章不演示。

2.1.1.案例

java 复制代码
/**
 * 使用 Cloneable 接口实现浅拷贝
 * 注意:只复制了对象本身,未复制内部的 List 字段
 *
 * 该类演示了 Java 原生 Cloneable 接口的使用方式。
 * clone() 方法调用 super.clone(),仅复制对象自身,不复制引用字段(如 List)
 * 因此,克隆后的对象与原对象共享同一个 List 实例,修改其中一个会影响另一个。
 * 适用于对象结构简单、无需深拷贝的场景。
 *
 * @author demo
 */
public class ShallowCloneWithCloneable implements Cloneable {
    private String name;
    private List<String> tags = new ArrayList<>();

    public ShallowCloneWithCloneable(String name) {
        //注意:String是不可变的,所以浅克隆和深克隆效果一致
        this.name = name;
        //赋默认值,方便查看是否被可弄
        this.tags.add("default");
    }

    @Override
    public ShallowCloneWithCloneable clone() {
        try {
            return (ShallowCloneWithCloneable) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new RuntimeException(e);
        }
    }

    public void addTag(String tag) {
        tags.add(tag);
    }

    public void display() {
        System.out.println("Name: " + name);
        System.out.println("Tags: " + tags);
    }
}

    public static void main(String[] args) {
        // 创建原始对象
        ShallowCloneWithCloneable original = new ShallowCloneWithCloneable("Original Object");
        System.out.println("原始对象:");
        original.display();

        // 克隆对象
        ShallowCloneWithCloneable copy = original.clone();
        System.out.println("克隆对象:");
        copy.display();

        // 修改克隆对象的引用字段
        System.out.println("修改克隆对象的 tags...");
        copy.addTag("new-tag");

        // 查看原始对象是否受影响
        System.out.println("原始对象现在的状态:");
        original.display();
        System.out.println("克隆对象现在的状态:");
        copy.display();
    }

2.2.2.运行结果

原始对象:

Name: Original Object

Tags: [default]

克隆对象:

Name: Original Object

Tags: [default]

修改克隆对象的 tags...

原始对象现在的状态:

Name: Original Object

Tags: [default, new-tag]

克隆对象现在的状态:

Name: Original Object

Tags: [default, new-tag]

2.2.序列化与反序列化机制实现

2.2.1.案例

java 复制代码
/**
 * 使用序列化与反序列化机制实现深拷贝
 * 注意:所有字段都会被重新创建,包括引用类型字段
 *
 * 该类演示了如何通过 Java 的序列化和反序列化机制实现真正的深拷贝。
 * 对象及其所有引用字段都会被完全复制,确保克隆后的对象与原对象完全独立。
 * 适用于复杂对象的深拷贝,无需手动复制字段。
 * 要求类必须实现 Serializable 接口。
 *
 * @author demo
 */
public class SerializableDeepClone implements Serializable {
    private String name;
    private List<String> tags = new ArrayList<>();

    public SerializableDeepClone(String name) {
        this.name = name;
        this.tags.add("default");
    }

    /**
     * 深拷贝方法
     * @return 一个新的、独立的对象副本
     */
    public SerializableDeepClone clone() {
        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 (SerializableDeepClone) ois.readObject();
        } catch (Exception e) {
            throw new RuntimeException("深拷贝失败", e);
        }
    }

    public void addTag(String tag) {
        tags.add(tag);
    }

    public void display() {
        System.out.println("Name: " + name);
        System.out.println("Tags: " + tags);
    }
}

public static void main(String[] args) {
        // 创建原始对象
        SerializableDeepClone original = new SerializableDeepClone("Original Object");
        System.out.println("原始对象:");
        original.display();

        // 克隆对象
        SerializableDeepClone copy = original.clone();
        System.out.println("\n克隆对象:");
        copy.display();

        // 修改克隆对象的引用字段
        System.out.println("\n修改克隆对象的 tags...");
        copy.addTag("new-tag");

        // 查看原始对象是否受影响
        System.out.println("\n原始对象现在的状态:");
        original.display();
        System.out.println("\n克隆对象现在的状态:");
        copy.display();
    }

2.2.2.运行结果

原始对象:

Name: Original Object

Tags: [default]

克隆对象:

Name: Original Object

Tags: [default]

修改克隆对象的 tags...

原始对象现在的状态:

Name: Original Object

Tags: [default]

克隆对象现在的状态:

Name: Original Object

Tags: [default, new-tag]

2.3. SerializationUtils实现

2.3.1.案例

XML 复制代码
<!--引入依赖-->    
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.12.0</version>
</dependency>
java 复制代码
/**
 * 使用 Apache Commons 的 SerializationUtils.clone() 实现深拷贝
 * 注意:所有字段都会被重新创建,包括引用类型字段
 *
 * 该类演示了如何通过 Apache Commons Lang 提供的 SerializationUtils.clone() 方法实现真正的深拷贝。
 * 对象及其所有引用字段都会被完全复制,确保克隆后的对象与原对象完全独立。
 * 适用于复杂对象的深拷贝,简化开发并避免手动复制字段。
 * 要求类必须实现 Serializable 接口。
 *
 * @author demo
 */
public class SerializableWithUtilsClone implements Serializable {
    private String name;
    private List<String> tags = new ArrayList<>();

    public SerializableWithUtilsClone(String name) {
        this.name = name;
        this.tags.add("default");
    }

    /**
     * 深拷贝方法,使用 Apache Commons Lang 的 SerializationUtils.clone()
     * @return 一个新的、独立的对象副本
     */
    public SerializableWithUtilsClone deepCopy() {
        return SerializationUtils.clone(this);
    }

    public void addTag(String tag) {
        tags.add(tag);
    }

    public void display() {
        System.out.println("Name: " + name);
        System.out.println("Tags: " + tags);
    }
}

    public static void main(String[] args) {
        // 创建原始对象
        SerializableWithUtilsClone original = new SerializableWithUtilsClone("Original Object");
        System.out.println("原始对象:");
        original.display();

        // 克隆对象
        SerializableWithUtilsClone copy = original.deepCopy();
        System.out.println("克隆对象:");
        copy.display();

        // 修改克隆对象的引用字段
        System.out.println("修改克隆对象的 tags...");
        copy.addTag("new-tag");

        // 查看原始对象是否受影响
        System.out.println("原始对象现在的状态:");
        original.display();
        System.out.println("克隆对象现在的状态:");
        copy.display();
    }

2.3.2.运行结果

原始对象:

Name: Original Object

Tags: [default]

克隆对象:

Name: Original Object

Tags: [default]

修改克隆对象的 tags...

原始对象现在的状态:

Name: Original Object

Tags: [default]

克隆对象现在的状态:

Name: Original Object

Tags: [default, new-tag]
💡 如果本文对你有帮助,点击右上角【订阅专栏】或左上角关注我

🔔 完整的23中设计模式干货,第一时间推送给你!

🔔 有什么问题也可以在评论区讨论🤝🤝🤝

相关推荐
武子康35 分钟前
Java-80 深入浅出 RPC Dubbo 动态服务降级:从雪崩防护到配置中心秒级生效
java·分布式·后端·spring·微服务·rpc·dubbo
YuTaoShao3 小时前
【LeetCode 热题 100】131. 分割回文串——回溯
java·算法·leetcode·深度优先
源码_V_saaskw4 小时前
JAVA图文短视频交友+自营商城系统源码支持小程序+Android+IOS+H5
java·微信小程序·小程序·uni-app·音视频·交友
超浪的晨4 小时前
Java UDP 通信详解:从基础到实战,彻底掌握无连接网络编程
java·开发语言·后端·学习·个人开发
双力臂4044 小时前
Spring Boot 单元测试进阶:JUnit5 + Mock测试与切片测试实战及覆盖率报告生成
java·spring boot·后端·单元测试
Edingbrugh.南空5 小时前
Aerospike与Redis深度对比:从架构到性能的全方位解析
java·开发语言·spring
QQ_4376643145 小时前
C++11 右值引用 Lambda 表达式
java·开发语言·c++
永卿0015 小时前
设计模式-迭代器模式
java·设计模式·迭代器模式
使二颗心免于哀伤5 小时前
《设计模式之禅》笔记摘录 - 10.装饰模式
笔记·设计模式
誰能久伴不乏5 小时前
Linux如何执行系统调用及高效执行系统调用:深入浅出的解析
java·服务器·前端