(C++实现)——原型模式(Prototype Pattern)

2024-06-15 02:58

本文主要是介绍(C++实现)——原型模式(Prototype Pattern),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

解决的问题:

用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。这个其实和C++的拷贝构造函数的作用是一致的,实际上就是动态抽取当前对象运行时的状态。


类图结构:     

客户(Client)角色:客户类提出创建对象的请求。
抽象原型(Prototype)角色:这是一个抽象角色,通常由一个C#接口或抽象类实现。此角色给出所有的具体原型类所需的接口。在C#中,抽象原型角色通常实现了ICloneable接口。
具体原型(Concrete Prototype)角色:被复制的对象。此角色需要实现抽象原型角色所要求的接口。


样例实现:

例子参照wuzhekai1985的简历的例子,代码拷贝如下:

[cpp]  view plain copy
  1. // CplusplusPrototype.cpp : Defines the entry point for the console application.  
  2. //  
  3. #include "stdafx.h"  
  4. #include<iostream>  
  5. #include<vector>  
  6. #include<assert.h>  
  7. using namespace std;  
  8. //父类    
  9. class Resume    
  10. {    
  11. protected:    
  12.     char *name;    
  13. public:    
  14.     Resume() {}    
  15.     virtual ~Resume() {}    
  16.     virtual Resume* Clone() { return NULL; }    
  17.     virtual void Set(char *n) {}    
  18.     virtual void Show() {}    
  19. };   
  20. class ResumeA : public Resume    
  21. {    
  22. public:    
  23.     ResumeA(const char *str);  //构造函数    
  24.     ResumeA(const ResumeA &r); //拷贝构造函数    
  25.     ~ResumeA();                //析构函数    
  26.     ResumeA* Clone();          //克隆,关键所在    
  27.     void Show();               //显示内容    
  28. };    
  29. ResumeA::ResumeA(const char *str)     
  30. {    
  31.     if(str == NULL) {    
  32.         name = new char[1];     
  33.         name[0] = '\0';     
  34.     }    
  35.     else {    
  36.         name = new char[strlen(str)+1];    
  37.         strcpy(name, str);    
  38.     }    
  39. }    
  40. ResumeA::~ResumeA() { delete [] name;}    
  41. ResumeA::ResumeA(const ResumeA &r) {    
  42.     name = new char[strlen(r.name)+1];    
  43.     strcpy(name, r.name);    
  44. }    
  45. ResumeA* ResumeA::Clone() {    
  46.     return new ResumeA(*this);    
  47. }    
  48. void ResumeA::Show() {    
  49.     cout<<"ResumeA name : "<<name<<endl;     
  50. }   
  51.   
  52. class ResumeB : public Resume    
  53. {    
  54. public:    
  55.     ResumeB(const char *str);  //构造函数    
  56.     ResumeB(const ResumeB &r); //拷贝构造函数    
  57.     ~ResumeB();                //析构函数    
  58.     ResumeB* Clone();          //克隆,关键所在    
  59.     void Show();               //显示内容    
  60. };    
  61. ResumeB::ResumeB(const char *str)     
  62. {    
  63.     if(str == NULL) {    
  64.         name = new char[1];     
  65.         name[0] = '\0';     
  66.     }    
  67.     else {    
  68.         name = new char[strlen(str)+1];    
  69.         strcpy(name, str);    
  70.     }    
  71. }    
  72. ResumeB::~ResumeB() { delete [] name;}    
  73. ResumeB::ResumeB(const ResumeB &r) {    
  74.     name = new char[strlen(r.name)+1];    
  75.     strcpy(name, r.name);    
  76. }    
  77. ResumeB* ResumeB::Clone() {    
  78.     return new ResumeB(*this);    
  79. }    
  80. void ResumeB::Show() {    
  81.     cout<<"ResumeB name : "<<name<<endl;     
  82. }   
  83.   
  84. int _tmain(int argc, _TCHAR* argv[])  
  85. {  
  86.     Resume *r1 = new ResumeA("A");    
  87.     Resume *r2 = new ResumeB("B");    
  88.     Resume *r3 = r1->Clone();    
  89.     Resume *r4 = r2->Clone();    
  90.     r1->Show(); r2->Show();    
  91.     //删除r1,r2    
  92.     delete r1; delete r2;       
  93.     r1 = r2 = NULL;    
  94.     //深拷贝所以对r3,r4无影响    
  95.     r3->Show(); r4->Show();    
  96.     delete r3; delete r4;    
  97.     r3 = r4 = NULL;       
  98.     return 0;  
  99. }  


带Prototype Manager的原型模式:

客户(Client)角色:客户端类向原型管理器提出创建对象的请求。
抽象原型(Prototype)角色:这是一个抽象角色,通常由一个C#接口或抽象类实现。此角色给出所有的具体原型类所需的接口。在C#中,抽象原型角色通常实现了ICloneable接口。
具体原型(Concrete Prototype)角色:被复制的对象。此角色需要实现抽象的原型角色所要求的接口。
原型管理器(Prototype Manager)角色:创建具体原型类的对象,并记录每一个被创建的对象。

代码实现如下:

[cpp]  view plain copy
  1. // CplusplusPrototype.cpp : Defines the entry point for the console application.  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5. #include<iostream>  
  6. #include<vector>  
  7. #include<assert.h>  
  8. using namespace std;  
  9. //父类    
  10. class Resume    
  11. {    
  12. protected:    
  13.     char *name;    
  14. public:    
  15.     Resume() {}    
  16.     virtual ~Resume() {}    
  17.     virtual Resume* Clone() { return NULL; }    
  18.     virtual void Set(char *n) {}    
  19.     virtual void Show() {}    
  20. };   
  21. class ResumeA : public Resume    
  22. {    
  23. public:    
  24.     ResumeA(const char *str);  //构造函数    
  25.     ResumeA(const ResumeA &r); //拷贝构造函数    
  26.     ~ResumeA();                //析构函数    
  27.     ResumeA* Clone();          //克隆,关键所在    
  28.     void Show();               //显示内容    
  29. };    
  30. ResumeA::ResumeA(const char *str)     
  31. {    
  32.     if(str == NULL) {    
  33.         name = new char[1];     
  34.         name[0] = '\0';     
  35.     }    
  36.     else {    
  37.         name = new char[strlen(str)+1];    
  38.         strcpy(name, str);    
  39.     }    
  40. }    
  41. ResumeA::~ResumeA() { delete [] name;}    
  42. ResumeA::ResumeA(const ResumeA &r) {    
  43.     name = new char[strlen(r.name)+1];    
  44.     strcpy(name, r.name);    
  45. }    
  46. ResumeA* ResumeA::Clone() {    
  47.     return new ResumeA(*this);    
  48. }    
  49. void ResumeA::Show() {    
  50.     cout<<"ResumeA name : "<<name<<endl;     
  51. }   
  52.   
  53. class ResumeB : public Resume    
  54. {    
  55. public:    
  56.     ResumeB(const char *str);  //构造函数    
  57.     ResumeB(const ResumeB &r); //拷贝构造函数    
  58.     ~ResumeB();                //析构函数    
  59.     ResumeB* Clone();          //克隆,关键所在    
  60.     void Show();               //显示内容    
  61. };    
  62. ResumeB::ResumeB(const char *str)     
  63. {    
  64.     if(str == NULL) {    
  65.         name = new char[1];     
  66.         name[0] = '\0';     
  67.     }    
  68.     else {    
  69.         name = new char[strlen(str)+1];    
  70.         strcpy(name, str);    
  71.     }    
  72. }    
  73. ResumeB::~ResumeB() { delete [] name;}    
  74. ResumeB::ResumeB(const ResumeB &r) {    
  75.     name = new char[strlen(r.name)+1];    
  76.     strcpy(name, r.name);    
  77. }    
  78. ResumeB* ResumeB::Clone() {    
  79.     return new ResumeB(*this);    
  80. }    
  81. void ResumeB::Show() {    
  82.     cout<<"ResumeB name : "<<name<<endl;     
  83. }   
  84.   
  85. class ResumeManager  
  86. {  
  87. private:  
  88.     vector<Resume *> mResume;  
  89. public:  
  90.     ResumeManager()  
  91.     {  
  92.   
  93.     }  
  94.     void add(Resume * resume)  
  95.     {  
  96.         mResume.push_back(resume);  
  97.     }  
  98.   
  99.      Resume * get(int index) const  
  100.     {  
  101.         assert(index>=0 && index<mResume.size());  
  102.         return mResume[index];  
  103.     }  
  104. };  
  105.   
  106. int _tmain(int argc, _TCHAR* argv[])  
  107. {  
  108.     ResumeManager *manager = new ResumeManager();  
  109.     Resume *r1 = new ResumeA("A");    
  110.     Resume *r2 = new ResumeB("B");    
  111.     manager->add(r1);  
  112.     manager->add(r2);  
  113.     manager->get(0)->Show();   
  114.     manager->get(1)->Show();    
  115.     Resume *r3 = manager->get(0)->Clone();    
  116.     Resume *r4 = manager->get(1)->Clone();   
  117.   
  118.     //删除r1,r2    
  119.     delete r1; delete r2;       
  120.     r1 = r2 = NULL;    
  121.     //深拷贝所以对r3,r4无影响    
  122.     r3->Show(); r4->Show();    
  123.     delete r3; delete r4;    
  124.     r3 = r4 = NULL;   
  125.     return 0;  
  126. }  

实现要点:

1.使用原型管理器,体现在一个系统中原型数目不固定时,可以动态的创建和销毁。

2.实现克隆操作,在.NET中可以使用Object类的MemberwiseClone()方法来实现对象的浅表拷贝或通过序列化的方式来实现深拷贝,在C++中就是拷贝构造函数的作用。

3.Prototype模式同样用于隔离类对象的使用者和具体类型(易变类)之间的耦合关系,它同样要求这些“易变类”拥有稳定的接口。


效果:

1.它对客户隐藏了具体的产品类,因此减少了客户知道的名字的数目。

2. Prototype模式允许客户只通过注册原型实例就可以将一个具体产品类并入到系统中,客户可以在运行时刻建立和删除原型。

3.减少了子类构造,Prototype模式是克隆一个原型而不是请求工厂方法创建一个,所以它不需要一个与具体产品类平行的Creater类层次。

4.Portotype模式具有给一个应用软件动态加载新功能的能力。由于Prototype的独立性较高,可以很容易动态加载新功能而不影响老系统。

5.产品类不需要非得有任何事先确定的等级结构,因为Prototype模式适用于任何的等级结构

6.Prototype模式的最主要缺点就是每一个类必须配备一个克隆方法。而且这个克隆方法需要对类的功能进行通盘考虑,这对全新的类来说不是很难,但对已有的类进行改造时,不一定是件容易的事。


适用性:

1. 当一个系统应该独立于他的产品创建、构成和表示时,需要使用原型模式

2. 当要实例化的类是在运行时刻指定时,如通过动态装载

3. 为了避免创建一个与产品类层次平行的工厂类层次时

4. 当一个类的实例只能有几个不同状态组合中的一种时,建立相应数目的原型并克隆他们可能比每次用合适的状态手工实例化该类更方便一些。



LCL_data原创于CSDN.NET【http://blog.csdn.net/lcl_data/article/details/8764228】

这篇关于(C++实现)——原型模式(Prototype Pattern)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1062244

相关文章

使用Python和OpenCV库实现实时颜色识别系统

《使用Python和OpenCV库实现实时颜色识别系统》:本文主要介绍使用Python和OpenCV库实现的实时颜色识别系统,这个系统能够通过摄像头捕捉视频流,并在视频中指定区域内识别主要颜色(红... 目录一、引言二、系统概述三、代码解析1. 导入库2. 颜色识别函数3. 主程序循环四、HSV色彩空间详解

Windows下C++使用SQLitede的操作过程

《Windows下C++使用SQLitede的操作过程》本文介绍了Windows下C++使用SQLite的安装配置、CppSQLite库封装优势、核心功能(如数据库连接、事务管理)、跨平台支持及性能优... 目录Windows下C++使用SQLite1、安装2、代码示例CppSQLite:C++轻松操作SQ

PostgreSQL中MVCC 机制的实现

《PostgreSQL中MVCC机制的实现》本文主要介绍了PostgreSQL中MVCC机制的实现,通过多版本数据存储、快照隔离和事务ID管理实现高并发读写,具有一定的参考价值,感兴趣的可以了解一下... 目录一 MVCC 基本原理python1.1 MVCC 核心概念1.2 与传统锁机制对比二 Postg

SpringBoot整合Flowable实现工作流的详细流程

《SpringBoot整合Flowable实现工作流的详细流程》Flowable是一个使用Java编写的轻量级业务流程引擎,Flowable流程引擎可用于部署BPMN2.0流程定义,创建这些流程定义的... 目录1、流程引擎介绍2、创建项目3、画流程图4、开发接口4.1 Java 类梳理4.2 查看流程图4

C++中RAII资源获取即初始化

《C++中RAII资源获取即初始化》RAII通过构造/析构自动管理资源生命周期,确保安全释放,本文就来介绍一下C++中的RAII技术及其应用,具有一定的参考价值,感兴趣的可以了解一下... 目录一、核心原理与机制二、标准库中的RAII实现三、自定义RAII类设计原则四、常见应用场景1. 内存管理2. 文件操

C++中零拷贝的多种实现方式

《C++中零拷贝的多种实现方式》本文主要介绍了C++中零拷贝的实现示例,旨在在减少数据在内存中的不必要复制,从而提高程序性能、降低内存使用并减少CPU消耗,零拷贝技术通过多种方式实现,下面就来了解一下... 目录一、C++中零拷贝技术的核心概念二、std::string_view 简介三、std::stri

C++高效内存池实现减少动态分配开销的解决方案

《C++高效内存池实现减少动态分配开销的解决方案》C++动态内存分配存在系统调用开销、碎片化和锁竞争等性能问题,内存池通过预分配、分块管理和缓存复用解决这些问题,下面就来了解一下... 目录一、C++内存分配的性能挑战二、内存池技术的核心原理三、主流内存池实现:TCMalloc与Jemalloc1. TCM

OpenCV实现实时颜色检测的示例

《OpenCV实现实时颜色检测的示例》本文主要介绍了OpenCV实现实时颜色检测的示例,通过HSV色彩空间转换和色调范围判断实现红黄绿蓝颜色检测,包含视频捕捉、区域标记、颜色分析等功能,具有一定的参考... 目录一、引言二、系统概述三、代码解析1. 导入库2. 颜色识别函数3. 主程序循环四、HSV色彩空间

Redis Cluster模式配置

《RedisCluster模式配置》:本文主要介绍RedisCluster模式配置,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录分片 一、分片的本质与核心价值二、分片实现方案对比 ‌三、分片算法详解1. ‌范围分片(顺序分片)‌2. ‌哈希分片3. ‌虚

Python实现精准提取 PDF中的文本,表格与图片

《Python实现精准提取PDF中的文本,表格与图片》在实际的系统开发中,处理PDF文件不仅限于读取整页文本,还有提取文档中的表格数据,图片或特定区域的内容,下面我们来看看如何使用Python实... 目录安装 python 库提取 PDF 文本内容:获取整页文本与指定区域内容获取页面上的所有文本内容获取