📖 背景故事
创业初期,小明每天加班写配送路线、配送策略、营销套餐。可当业务做大后,他发现大家常常下单“上次那个套餐”——
“老板,再来一个上次的奶茶+水果!”
“老样子,照搬昨天晚上的宵夜套餐!”
每天都要重新构建这些复杂的套餐组合,小明手速再快也累趴下了 🥵。
于是小明灵机一动:
“能不能把这些常见套餐复制粘贴,用一个模子刻出来?”💡
这时,原型模式救场了!
🌈 生活中类似的例子
-
Word 文档点“复制” → “粘贴”
-
游戏角色自定义后,保存为模板,创建新角色时快速复制
-
套餐模板、一键下单
😵 如果不用原型模式
每次都用建造者一步一步构建套餐?效率太低了!
用工厂创建?每次还要重新传配置?麻烦!
💡 小明的解决方案:原型模式登场!
小明定义了所有套餐都必须支持“克隆”,然后把常见的“模板套餐”先存下来,当用户要下单时,直接拷贝一份,改一点点就行了!
✅ 原型模式结构
-
原型接口:定义 clone 方法
-
具体原型类:实现 clone 自我复制
-
客户端:调用 clone 得到新的对象
🧠 原型模式 C++ 示例
抽象原型类
class ComboPrototype {
public:
virtual ComboPrototype* clone() = 0;
virtual void show() = 0;
virtual ~ComboPrototype() {}
};
具体原型类:奶茶 + 水果 套餐
class MilkTeaFruitCombo : public ComboPrototype {
public:
std::string name;
MilkTeaFruitCombo() {
name = "经典奶茶水果套餐 🍹🍉";
}
ComboPrototype* clone() override {
return new MilkTeaFruitCombo(*this);
}
void show() override {
std::cout << name << std::endl;
}
};
具体原型类:烧烤+可乐 宵夜套餐
class BBQNightCombo : public ComboPrototype {
public:
std::string name;
BBQNightCombo() {
name = "深夜烧烤可乐套餐 🍖🥤";
}
ComboPrototype* clone() override {
return new BBQNightCombo(*this);
}
void show() override {
std::cout << name << std::endl;
}
};
客户端代码
int main() {
// 小明的模板库
ComboPrototype* prototype1 = new MilkTeaFruitCombo();
ComboPrototype* prototype2 = new BBQNightCombo();
// 用户:我要“老样子”套餐!
ComboPrototype* order1 = prototype1->clone();
ComboPrototype* order2 = prototype2->clone();
// 展示结果
std::cout << "下单成功!您的套餐是:" << std::endl;
order1->show();
order2->show();
// 清理
delete prototype1;
delete prototype2;
delete order1;
delete order2;
return 0;
}
🤯 不使用原型模式怎么办?
// 每次都得重新 new + 配置属性
class Combo {
public:
std::string name;
Combo(const std::string& n) : name(n) {}
void show() { std::cout << name << std::endl; }
};
int main() {
Combo* combo1 = new Combo("经典奶茶水果套餐 🍹🍉");
Combo* combo2 = new Combo("深夜烧烤可乐套餐 🍖🥤");
combo1->show();
combo2->show();
delete combo1;
delete combo2;
}
缺点:
- 重复构造逻辑
- 如果对象构造复杂,效率低
- 不便于复制已有对象的全部状态
💬 小明的总结(带表情包)
“每次重复创建套餐,累得像🐂!现在我直接复制模板,一键下单,效率飙升⚡!原型模式,YYDS!🙌”