设计模式之原型模式

简单来说,原型模式(Prototype Pattern) 的核心思想就是:"与其从零创建一个新对象,不如直接克隆一个现有的对象。"

想象一下,如果你需要给 10 个不同的部门提供你的身份证副本,有两种方法:

  1. 非原型模式(手动重绘): 你拿出一张白纸,对着身份证,一笔一划地把头像、文字、国徽全部画出来。每办一个业务,你就得重新画一遍。

  2. 原型模式(复印机): 你把身份证(原型)放在复印机上,按下"复印"键(clone)。复印机直接扫描物理特征并产生副本。


1. 不使用原型模式:手动重绘

在这种模式下,客户端(打印店员工)必须知道身份证的所有细节(姓名、号码等),并且每需要一个副本,都要重新调用构造函数并手动设置属性。

复制代码
#include <iostream>
#include <string>

class IDCard {
public:
    std::string name;
    std::string idNumber;
    std::string purpose;

    // 构造函数:模拟"办证"过程,非常麻烦
    IDCard(std::string n, std::string id) : name(n), idNumber(id) {
        std::cout << "[系统] 正在进行繁琐的身份核验、制卡..." << std::endl;
    }
};

// 客户端代码
int main() {
    // 假设我们已经有一个原件了
    IDCard myID("张三", "110101...");

    // 需求:现在需要两个副本,分别给银行和健身房
    // 缺点:你必须手动重复输入所有信息,万一 idNumber 输错一位就麻烦了
    IDCard copy1(myID.name, myID.idNumber); 
    copy1.purpose = "银行开户";

    IDCard copy2(myID.name, myID.idNumber);
    copy2.purpose = "健身房会员";

    return 0;
}

2. 使用原型模式:复印机一键克隆

在这种模式下,身份证类自带一个 clone() 方法。客户端不需要关心身份证里到底有什么,只需要说"给我复印一份"即可。

复制代码
#include <iostream>
#include <string>
#include <memory>

// 抽象原型
class Prototype {
public:
    virtual ~Prototype() {}
    virtual std::unique_ptr<Prototype> clone() const = 0;
    virtual void setPurpose(std::string p) = 0;
    virtual void display() const = 0;
};

// 具体原型:身份证
class IDCard : public Prototype {
private:
    std::string name;
    std::string idNumber;
    std::string purpose;

public:
    IDCard(std::string n, std::string id) : name(n), idNumber(id), purpose("原件") {
        std::cout << "[系统] 正在进行繁琐的身份核验、制卡..." << std::endl;
    }

    // 关键:克隆方法(利用拷贝构造函数)
    std::unique_ptr<Prototype> clone() const override {
        return std::make_unique<IDCard>(*this); 
    }

    void setPurpose(std::string p) override { purpose = p; }
    
    void display() const override {
        std::cout << "姓名:" << name << " | 用途:" << purpose << std::endl;
    }
};

// 客户端代码
int main() {
    // 1. 只有一份原件
    std::unique_ptr<Prototype> myID = std::make_unique<IDCard>("张三", "110101...");

    // 2. 需求:需要副本
    // 优点:无需再次输入姓名和号码,直接克隆,既快又准
    auto copy1 = myID->clone();
    copy1->setPurpose("银行开户");

    auto copy2 = myID->clone();
    copy2->setPurpose("健身房会员");

    copy1->display();
    copy2->display();

    return 0;
}

3. 直观对比总结

特性 不使用原型模式 使用原型模式
创建方式 必须 new 一个具体类。 调用已存在对象的 clone()
依赖程度 高。 必须知道对象的构造函数参数。 低。 只需要知道 clone() 接口。
复杂性 每次创建都要手动重新赋值(容易出错)。 状态自动复制,只需修改差异部分。
性能开销 大。 每次都要跑一遍复杂的构造逻辑。 小。 通常是高效的内存拷贝。
适用场景 对象很简单,属性很少。 对象初始化极慢,或者属性极其复杂。
相关推荐
J_liaty5 小时前
23种设计模式一命令模式
设计模式·命令模式
J_liaty15 小时前
23种设计模式一迭代器模式
设计模式·迭代器模式
驴儿响叮当201019 小时前
设计模式之策略模式
设计模式·策略模式
驴儿响叮当201021 小时前
设计模式之中介模式
设计模式
驴儿响叮当20101 天前
设计模式之命令模式
设计模式·命令模式
驴儿响叮当20101 天前
设计模式之适配器模式
设计模式·适配器模式
HEU_firejef1 天前
设计模式——代理模式
设计模式·代理模式
Coder_Boy_1 天前
从单体并发工具类到分布式并发:思想演进与最佳实践(二)
java·spring boot·分布式·微服务·设计模式
geovindu2 天前
python: Memento Pattern
开发语言·python·设计模式·备忘录模式