【从零入门23种设计模式04】创建型之原型模式

祝大家除夕快乐新年发大财!!!

一、原型模式的核心定义

原型模式是一种创建型设计模式 ,核心思想是:基于一个已存在的 "原型对象",通过 "克隆(复制)" 的方式创建新对象,而非通过 new 关键字从头初始化。可以类比成 "复印文件":已有一份写好的文件(原型),想要多份相同的文件时,直接复印(克隆)比重新手写(new + 初始化)效率高得多。

二、核心适用场景

当满足以下条件时,优先考虑原型模式:

  1. 对象创建成本高(比如初始化需要大量 IO 操作、数据库查询、网络请求);
  2. 需要频繁创建结构 / 属性相似的对象;
  3. 希望隐藏对象创建的复杂细节,只关注 "复制已有对象";
  4. 避免构造函数的复杂逻辑(比如构造函数参数过多、逻辑嵌套)。

三、实现方式(以 Java 为例)

Java 中实现原型模式的核心是:

  • 实现 Cloneable 接口(标记接口,仅表明该类支持克隆,无任何方法);
  • 重写 Object 类的 clone() 方法(Object 类的 clone() 是 protected,需重写为 public)。

原型模式分为两种核心克隆方式:浅克隆深克隆(新手最容易踩坑的点)。

1. 浅克隆(Shallow Clone)
定义

只克隆对象的 "基本数据类型成员变量",对于 "引用类型成员变量",仅克隆引用地址(新对象和原型对象共享同一个引用对象)。

代码示例
复制代码
// 原型类(实现Cloneable接口)
class User implements Cloneable {
    // 基本数据类型
    private int id;
    // 引用数据类型(自定义对象)
    private Address address;

    // 构造函数
    public User(int id, Address address) {
        this.id = id;
        this.address = address;
    }

    // 重写clone方法(浅克隆)
    @Override
    public User clone() {
        try {
            // 调用Object的clone()方法,实现浅克隆
            return (User) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new AssertionError(); // 不会触发,因为实现了Cloneable
        }
    }

    // getter/setter(简化展示)
    public int getId() { return id; }
    public Address getAddress() { return address; }
    public void setId(int id) { this.id = id; }
}

// 引用类型成员类
class Address {
    private String city;

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

    public String getCity() { return city; }
    public void setCity(String city) { this.city = city; }
}

// 测试浅克隆
public class PrototypeTest {
    public static void main(String[] args) {
        // 1. 创建原型对象
        Address addr = new Address("北京");
        User prototype = new User(1, addr);

        // 2. 克隆新对象
        User cloneUser = prototype.clone();

        // 3. 验证结果
        System.out.println("原型对象id:" + prototype.getId()); // 1
        System.out.println("克隆对象id:" + cloneUser.getId()); // 1
        System.out.println("原型地址:" + prototype.getAddress().getCity()); // 北京
        System.out.println("克隆地址:" + cloneUser.getAddress().getCity()); // 北京

        // 4. 修改原型的引用对象属性 → 克隆对象的属性也会变(共享引用)
        addr.setCity("上海");
        System.out.println("修改后原型地址:" + prototype.getAddress().getCity()); // 上海
        System.out.println("修改后克隆地址:" + cloneUser.getAddress().getCity()); // 上海
    }
}
关键结论

浅克隆的问题:引用类型成员变量是 "共享" 的,修改原型的引用对象,克隆对象也会受影响

2. 深克隆(Deep Clone)
定义

不仅克隆基本数据类型,还会克隆所有引用类型成员变量(新对象和原型对象的引用类型成员变量是独立的)。

实现方式(常用 2 种)
方式 1:手动克隆引用对象

clone() 方法中,手动克隆引用类型成员变量:

复制代码
@Override
public User clone() {
    try {
        User cloneUser = (User) super.clone();
        // 手动克隆引用类型成员(深克隆核心)
        cloneUser.address = new Address(this.address.getCity());
        return cloneUser;
    } catch (CloneNotSupportedException e) {
        throw new AssertionError();
    }
}

测试结果:修改原型的 address,克隆对象的 address 不会变。

方式 2:序列化(推荐,适合复杂对象)

通过序列化将对象转为字节流,再反序列化为新对象(天然实现深克隆):

复制代码
// 需让User和Address实现Serializable接口
class User implements Serializable {
    private int id;
    private Address address;

    // 深克隆方法(序列化)
    public User deepClone() throws IOException, ClassNotFoundException {
        // 1. 序列化:将对象写入字节流
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(this);

        // 2. 反序列化:从字节流读取新对象
        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bis);
        return (User) ois.readObject();
    }
}

class Address implements Serializable {
    private String city;
    // 构造函数+getter/setter
}

四、原型模式的优缺点

优点 缺点
1. 简化对象创建,避免重复初始化逻辑; 2. 提高创建效率(尤其对象初始化成本高时); 3. 隐藏对象创建细节,降低耦合; 1. 深克隆实现复杂(引用类型嵌套多时,手动克隆易遗漏); 2. 每个原型类都需实现克隆逻辑,增加代码量; 3. 需注意 Cloneable 接口的陷阱(未实现会抛异常);

五、总结

  1. 核心本质:原型模式是 "复制已有对象" 而非 "新建对象",核心解决 "对象创建成本高" 的问题;
  2. 关键区分:浅克隆共享引用对象(简单但有数据安全风险),深克隆完全独立(复杂但安全);
  3. 使用建议:简单对象用浅克隆,包含多层引用类型的复杂对象用序列化实现深克隆;
  4. 语言支持 :Java 通过 Cloneable + clone() 实现,Python 通过 copy 模块(copy.copy() 浅克隆、copy.deepcopy() 深克隆)实现,核心逻辑一致。
相关推荐
一条大祥脚1 小时前
中心拓展法解决回文问题
算法
1 小时前
2.19列阵,私聊调配,求小数位数个数
算法
weixin_477271692 小时前
马王堆帛书《周易》六十四貞如何读象(《函谷门》原创)
算法·图搜索算法
HrxXBagRHod9 小时前
三菱FX5U与3台三菱E700变频器专用协议通讯实战
设计模式
追随者永远是胜利者10 小时前
(LeetCode-Hot100)53. 最大子数组和
java·算法·leetcode·职场和发展·go
生成论实验室10 小时前
即事经:一种基于生成论的宇宙、生命与文明新范式
人工智能·科技·神经网络·算法·信息与通信
王老师青少年编程11 小时前
csp信奥赛c++高频考点假期集训(分模块进阶)
数据结构·c++·算法·csp·高频考点·信奥赛·集训