news 2026/8/27 8:26:00

原型模式-创建型

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
原型模式-创建型

一、原型模式

1.1、定义

原型实例指定创建对象的种类,并通过拷贝这些原型,创建新的对象。即克隆,细胞分裂等。

1.2、核心思想

通过复制现有对象(原型)来创建新对象,而不是通过new新建实例

1.3、为什么需要原型模式

问题场景

创建角色,以孙悟空为例

// 装备类classEquipment{private:std::string name;intpower;public:Equipment(std::string name,intpower):name(name),power(power){}Equipment*clone()const{returnnewEquipment(name,power);}std::stringgetName()const{returnname;}intgetPower()const{returnpower;}voiddisplay()const{std::cout<<" "<<name<<" (威力:"<<power<<")"<<std::endl;}};
classSunWuKong{private:std::string name;inthealth;intattack;std::vector<std::string>skills;std::vector<Equipment*>equipment;public:SunWuKong(std::string name,inthealth,intattack):name(name),health(health),attack(attack){// 初始化技能skills.push_back("七十二变");skills.push_back("筋斗云");skills.push_back("火眼金睛");skills.push_back("法天象地");skills.push_back("身外身");// 初始化装备equipment.push_back(newEquipment("金箍棒",1000));equipment.push_back(newEquipment("锁子黄金甲",500));equipment.push_back(newEquipment("凤翅紫静",300));equipment.push_back(newEquipment("藕丝步云履",200));}// 复制构造函数SunWuKong(constSunWuKong&other):name(other.name),health(other.health),attack(other.attack),skills(other.skills),equipment(other.equipment){}// 拷贝赋值运算符SunWuKong&operator=(constSunWuKong&other){if(this!=&other){name=other.name;health=other.health;attack=other.attack;skills=other.skills;equipment=other.equipment;}return*this;}~SunWuKong(){for(auto&eq:equipment){deleteeq;}}};// 创建分身voidcreateCloneMonkey(){// 创建本体SunWuKong*original=newSunWuKong("齐天大圣",1000,100);// 吹毛化兵,创建分身vector<SunWuKong*>clones;for(inti=0;i<100000;++i){std::count<<"创建第 "<<i<<" 个分身\n";SunWuKong*clone=newSunWuKong(*original);clones.push_back(clone);}deleteoriginal;// 删除分身for(auto&clone:clones){deleteclone;}}

问题点:

  1. 性能上:每次创建分身时,都需要初始化技能和装备,效率低下
  2. 灵活性差,如果修改了本体,分身不会自动进行更新
  3. 浅拷贝问题,容易导致双重释放或访问已释放内存

解决方案

使用原型模式之后

  1. 创建原型抽象类
classCharacterPrototype{public:virtual~CharacterPrototype(){}=default;virtualCharacterPrototype*clone()const=0;virtualvoiddisplay()const=0;virtualstd::stringgetName()const=0;virtualvoidsetName(std::string name)=0;};
  1. 具体原型类
classSunWuKong:publicCharacterPrototype{private:std::string name;inthealth;intattack;std::vector<std::string>skills;std::vector<Equipment*>equipment;public:SunWuKong(std::string name,inthealth,intattack):name(name),health(health),attack(attack){// 初始化技能skills.push_back("七十二变");skills.push_back("筋斗云");skills.push_back("火眼金睛");skills.push_back("法天象地");// 初始化装备equipment.push_back(newEquipment("金箍棒",1000));equipment.push_back(newEquipment("锁子黄金甲",500));equipment.push_back(newEquipment("凤翅紫金冠",300));equipment.push_back(newEquipment("藕丝步云履",200));}// 拷贝构造函数(采用深拷贝)SunWuKong(constSunWuKong&other){name=other.name;health=other.health;attack=other.attack;skills=other.skills;equipment.clear();for(auto&eq:other.equipment){equipment.push_back(eq->clone());}}// 拷贝赋值运算符(采用深拷贝)SunWuKong&operator=(constSunWuKong&other){if(this!=&other){name=other.name;health=other.health;attack=other.attack;skills=other.skills;equipment.clear();for(auto&eq:other.equipment){equipment.push_back(eq->clone());}}}// 克隆方法(核心)CharacterPrototype*clone()constoverride{returnnewSunWuKong(*this);// 调用拷贝构造函数}voidsetName(std::string name)override{this->name=name;}std::stringgetName()constoverride{returnname;}voiddisplay()constoverride{std::cout<<"name: "<<this->name<<" , "<<"health: "<<this->health<<" , "<<"attack: "<<this->attack<<" , "<<"skills: \n";for(constauto&skill:skills){std::cout<<skill<<" ";}std::cout<<"\n";std::cout<<"equipment:\n";for(constauto&eq:equipment){eq->display();}}~SunWuKong(){for(auto&eq:equipment){deleteeq;}}};
  1. 原型管理器
classPrototypeManager{private:std::unordered_map<std::string,CharacterPrototype*>prototypes;public:~PrototypeManager(){for(auto&pair:prototypes){deletepair.second;}}voidaddPrototype(std::string key,CharacterPrototype*prototype){prototypes[key]=prototype;}CharacterPrototype*getPrototype(std::string key){if(prototypes.find(key)!=prototypes.end()){returnprototypes[key]->clone();}returnnullptr;}};
  1. 使用
voidusePrototype(){// 1. 创建原型SunWukong*original=newSunWukong("齐天大圣孙悟空",1500,150);original->display();std::cout<<"\n--- 孙悟空吹毫毛变分身 ---\n";// 2. 创建多个分身std::vector<CharacterPrototype*>clones;for(inti=1;i<=30;i++){// 使用克隆方法创建分身CharacterPrototype*clone=original->clone();clone->setName("孙悟空分身"+to_string(i));clones.push_back(clone);}// 3. 分身展示for(auto&clone:clones){clone->display();}// 4. 清理内存for(auto&clone:clones){deleteclone;}deleteoriginal;}voidusePrototypeManager(){PrototypeManager manager;manager.addPrototype("孙悟空",newSunWuKong("齐天大圣孙悟空",1500,150));// 从管理器获取原型并克隆autocloneFromManager=manager.getPrototype("sunwukong");if(cloneFromManager){cloneFromManager->setName("管理器中克隆的分身");cloneFromManager->display();deletecloneFromManager;}}voidcomparison(){autostart1=std::chrono::high_resolution_clock::now();// 传统方式创建10000个分身std::vector<SunWuKong*>clones1;SunWuKong*original=newSunWuKong("齐天大圣",1000,100);for(inti=0;i<10000;i++){clones1.push_back(newSunWuKong("分身",1000,100));}autoend1=std::chrono::high_resolution_clock::now();autostart2=std::chrono::high_resolution_clock::now();// 原型模式创建10000个分身std::vector<CharacterPrototype*>clones2;for(inti=0;i<10000;i++){clones2.push_back(original->clone());}autoend2=std::chrono::high_resolution_clock::now();std::cout<<"传统方式耗时: "<<std::chrono::duration_cast<std::chrono::milliseconds>(end1-start1).count()<<"ms\n";std::cout<<"原型模式耗时: "<<std::chrono::duration_cast<std::chrono::milliseconds>(end2-start2).count()<<"ms\n";}

附上UML图:

二、总结

2.1、与传统方式进行对比

特点传统创建方式原型模式
性能低,每次都要执行完整初始化高,一次初始化,多次复制
内存每个对象独立内存可共享不变部分
代码复杂度高,需要实现clone
灵活性高,可动态修改原型
适用场景对象创建简单对象创建复杂,批量创建

2.2、深拷贝 VS 浅拷贝

  • 浅拷贝:亦可称为值拷贝。将源对象的值拷贝到目标对象中,如果对象中某个成员是指针类型数据,并且是在堆上创建的,那么源对象和目标对象都指向同一块内存区域,此时如果其中一个对象释放了内存,那么另一个对象的指针就会变成野指针。
  • 深拷贝:在拷贝的时候,先开辟出与源对象大小一样的空间,然后将源对象的内容拷贝到新开辟的空间中。这样无论哪个对象释放内存,都不会影响另一个对象的正常使用。

2.3、原型模式 VS 工厂模式

  • 原型模式:通过克隆原型对象来创建新的对象,适用于创建复杂对象,特别是当对象的创建过程较为耗时或复杂时。
  • 工厂模式:通过工厂方法来创建对象,适用于创建不同类型的对象,特别是当对象的创建逻辑较为复杂时。

三、附加

由于C++语法的灵活性,原型模式实现可以有多种方式

1. 结合智能指针版–原型模式

// 使用智能指针和移动语义classSunWuKong1:publicCharacterPrototype{private:string name;inthealth;intattack;vector<string>skills;vector<unique_ptr<Equipment>>equipment;// 使用unique_ptrpublic:SunWuKong1(string name,inthealth,intattack):name(name),health(health),attack(attack){// 初始化技能skills.push_back("七十二变");skills.push_back("筋斗云");skills.push_back("火眼金睛");skills.push_back("法天象地");// 初始化装备equipment.push_back(newEquipment("金箍棒",1000));equipment.push_back(newEquipment("锁子黄金甲",500));equipment.push_back(newEquipment("凤翅紫金冠",300));equipment.push_back(newEquipment("藕丝步云履",200));}// 使用移动构造函数提高效率SunWuKong1(SunWuKong1&&other)noexcept:name(move(other.name)),health(other.health),attack(other.attack),skills(move(other.skills)),equipment(move(other.equipment)){}CharacterPrototype*clone()constoverride{// 先创建一个副本autoclone=make_unique<SunWuKong1>(name,health,attack);// 深拷贝equipmentfor(constauto&eq:equipment){clone->equipment.push_back(make_unique<Equipment>(*eq));}returnclone.release();}};

2. 结合函数模板,通过注册的方式–原型模式

classPrototypeRegistry{private:staticunordered_map<string,function<unique_ptr<CharacterPrototype>()>>registry;public:staticvoidregisterPrototype(conststring&key,function<unique_ptr<CharacterPrototype>()>creator){registry[key]=move(creator);}staticunique_ptr<CharacterPrototype>clone(conststring&key){if(autoit=registry.find(key);it!=registry.end()){returnit->second();}returnnullptr;}};
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/25 22:48:18

Type-C领夹麦:重塑移动收音新体验

在短视频创作、直播带货、在线教育等场景井喷的当下&#xff0c;移动收音设备正经历从“可用”到“专业”的质变。Type-C接口LDR6500领夹麦克风凭借即插即用的便捷性、媲美录音棚的音质表现&#xff0c;以及与现代智能设备的无缝兼容性&#xff0c;迅速成为创作者、教育者、主播…

作者头像 李华
网站建设 2026/8/27 2:11:28

AI Agent与MCP协议:重构企业协作生态的实战指南

文章探讨了AI Agent的"超级工具箱"——MCP协议如何重构企业协作生态。介绍了工具三大属性&#xff08;契约化设计、权限最小化、可观测性&#xff09;和MCP四大核心原则&#xff08;标准化身份、任务驱动通信、能力发现、流式状态更新&#xff09;。通过商业案例展示…

作者头像 李华
网站建设 2026/8/27 1:59:41

左手职场右手AI:2025年最值得学习的10大国产大模型全解析

本文详细介绍了2025年中国市场十大主流AI大模型&#xff0c;包括DeepSeek、Kimi、元宝等&#xff0c;分析了各自专注领域、差异化优势及适用场景。文章指出国内大模型已从"比谁更大"进入"比谁更准、更合规"阶段&#xff0c;开源模型参数量激增&#xff0c;…

作者头像 李华
网站建设 2026/8/26 5:18:45

提升论文效率:10个AI工具搞定数学建模复现与LaTeX排版

还在为论文写作头痛&#xff1f;特别是数学建模的优秀论文复现与排版&#xff0c;时间紧、任务重&#xff0c;AI工具能帮上大忙吗&#xff1f;今天&#xff0c;我们评测10款热门AI论文写作工具&#xff0c;帮你精准筛选最适合的助手。aibiye&#xff1a;专注于语法润色与结构优…

作者头像 李华
网站建设 2026/8/27 7:32:06

19、AdobeAcrobatProDC

详情介绍 Adobe Acrobat Pro DC是由Adobe公司开发的一款PDF文档创作、编辑和管理软件&#xff0c;可为个人、教育者等提供高效、便捷、安全的文档处理体验。软件具有强大的PDF处理能力&#xff0c;支持将多个PDF导出为不同的文件格式&#xff0c;如Word、Excel或PowerPoint&am…

作者头像 李华