C++设计模式 之 原型模式

意图:

       用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

适用性:

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

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

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

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

prototype.h

[cpp]  view plain copy
  1. //设计模式之原型模式  
  2.   
  3. /* 
  4. 解析: 
  5. Prototype模式其实就是常说的"虚拟构造函数"一个实现,C++的实现机制中并没有支持这个特性, 
  6. 但是通过不同派生类实现的Clone接口函数可以完成与"虚拟构造函数"同样的效果.举一个例子来 
  7. 解释这个模式的作用,假设有一家店铺是配钥匙的,他对外提供配制钥匙的服务(提供Clone接口函 
  8. 数),你需要配什么钥匙它不知道只是提供这种服务,具体需要配什么钥匙只有到了真正看到钥匙 
  9. 的原型才能配好.也就是说,需要一个提供这个服务的对象,同时还需要一个原型(Prototype),不 
  10. 然不知道该配什么样的钥匙. 
  11.  
  12. */  
  13. //声明一个虚拟基类,所有的原型都从这个基类继承,  
  14. class prototype  
  15. {  
  16. public:  
  17.     prototype(){}  
  18.     virtual ~prototype(){}  
  19.     virtual prototype* clone() = 0;//纯虚函数,需要供继承者自行实现  
  20. };  
  21.   
  22. // 派生自Prototype,实现Clone方法  
  23. class concreateprototype1:public prototype  
  24. {  
  25. public:  
  26.     concreateprototype1();  
  27.     concreateprototype1(const concreateprototype1&);  
  28.     virtual ~concreateprototype1();  
  29.     virtual prototype* clone();  
  30. };  
  31.   
  32. // 派生自Prototype,实现Clone方法  
  33. class concreateprototype2:public prototype  
  34. {  
  35. public:  
  36.     concreateprototype2();  
  37.     concreateprototype2(const concreateprototype2&);  
  38.     virtual ~concreateprototype2();  
  39.     virtual prototype* clone();  
  40. };  

prototype.cpp

[cpp]  view plain copy
  1. #include "prototype.h"  
  2. #include <iostream>  
  3. using namespace std;  
  4. concreateprototype1::concreateprototype1()  
  5. {  
  6.     cout<<"concreteprototype1 create"<<endl;  
  7. }  
  8.   
  9. concreateprototype1::concreateprototype1(const concreateprototype1 &contype )  
  10. {  
  11.     cout<<"copy the concreteprototype1"<<endl;  
  12. }  
  13. concreateprototype1::~concreateprototype1()  
  14. {  
  15.     cout<<"destruction of concreteprototype1"<<endl;  
  16. }  
  17. prototype* concreateprototype1::clone()  
  18. {  
  19.     return new concreateprototype1(*this);  
  20. }  
  21.   
  22. concreateprototype2::concreateprototype2()  
  23. {  
  24.     cout<<"concreteprototype2 create"<<endl;  
  25. }  
  26.   
  27. concreateprototype2::concreateprototype2(const concreateprototype2 &contype )  
  28. {  
  29.     cout<<"copy the concreteprototype2"<<endl;  
  30. }  
  31. concreateprototype2::~concreateprototype2()  
  32. {  
  33.     cout<<"destruction of concreteprototype2"<<endl;  
  34. }  
  35. prototype* concreateprototype2::clone()  
  36. {  
  37.     return new concreateprototype2(*this);  
  38. }  

 

使用的时候可以这么使用:

[cpp]  view plain copy
  1. prototype *ptype1 = new concreateprototype1();  
  2. prototype *copytype1 = ptype1->clone();  
  3.   
  4. delete ptype1;  
  5. delete copytype1;  
这种情况是 浅复制,被复制的对象的所有变量都含有原来的对象相同的值,而所有的对其他对象的引用的仍指向原来的对象

所以,如果我们想修改任意一个引用指向的的对象,那么所有对象的这个引用这项对象都会进行修改:

比如,三个简历复制过来名字都是 XXX,而如果我们修改任意一个简历的名字为YYY,则三个简历名字都是YYY了,即浅复制。


所以,我们就更需要这样的一种需求,把要复制的对象所有引用的对象都复制一遍。这样复制出来的对象都是不同的,独立的,这种复制

方式为“深复制”!深复制会把引用对象的变量指向复制过的新对象,而不是原来的被引用的对象

但是深复制到底要复制多少层,需要事先考虑好!而且当心出现循环引用的问题!

代码:

resume.h

[cpp]  view plain copy
  1. //首先抽象一个基类  
  2. class resume  
  3. {  
  4. protected:  
  5.     char *name;  
  6. public:  
  7.     resume()  
  8.     {  
  9.     }  
  10.     virtual ~resume()  
  11.     {   
  12.     }  
  13.     virtual void set(const char *str)  
  14.     {  
  15.     }  
  16.     virtual void show()  
  17.     {   
  18.     }  
  19.     virtual resume* clone()  
  20.     {  
  21.         return 0;  
  22.     }  
  23. };  
  24.   
  25. class ResumeA : public resume  
  26. {  
  27. public:  
  28.     ResumeA(const char *str);  //构造函数  
  29.     ResumeA(const ResumeA &r); //拷贝构造函数  
  30.     ~ResumeA();                //析构函数  
  31.     ResumeA* clone();          //克隆,关键所在  
  32.     void show();               //显示内容  
  33. };  
  34.     
  35. class ResumeB : public resume  
  36. {  
  37. public:  
  38.     ResumeB(const char *str);  //构造函数  
  39.     ResumeB(const ResumeB &r); //拷贝构造函数  
  40.     ~ResumeB();                //析构函数  
  41.     ResumeB* clone();          //克隆,关键所在  
  42.     void show();               //显示内容  
  43. };  

resume.cpp

[cpp]  view plain copy
  1. #include "resume.h"  
  2. #include <iostream>
  3. using namespace std;  
  4. ResumeA::ResumeA(const char *str)   
  5. {  
  6.     if(str == NULL) {  
  7.         name = new char[1];   
  8.         name[0] = '\0';   
  9.     }  
  10.     else {  
  11.         name = new char[strlen(str)+1];  
  12.         strcpy(name, str);  
  13.     }  
  14. }  
  15. ResumeA::~ResumeA() { delete [] name;}  
  16. ResumeA::ResumeA(const ResumeA &r) {  
  17.     name = new char[strlen(r.name)+1];  
  18.     strcpy(name, r.name);  
  19. }  
  20. ResumeA* ResumeA::clone() {  
  21.     return new ResumeA(*this);  
  22. }  
  23. void ResumeA::show() {  
  24.     cout<<"ResumeA name : "<<name<<endl;   
  25. }  
  26.   
  27. ResumeB::ResumeB(const char *str)   
  28. {  
  29.     if(str == NULL) {  
  30.         name = new char[1];   
  31.         name[0] = '\0';   
  32.     }  
  33.     else {  
  34.         name = new char[strlen(str)+1];  
  35.         strcpy(name, str);  
  36.     }  
  37. }  
  38. ResumeB::~ResumeB() { delete [] name;}  
  39. ResumeB::ResumeB(const ResumeB &r) {  
  40.     name = new char[strlen(r.name)+1];  
  41.     strcpy(name, r.name);  
  42. }  
  43. ResumeB* ResumeB::clone() {  
  44.     return new ResumeB(*this);  
  45. }  
  46. void ResumeB::show() {  
  47.     cout<<"ResumeB name : "<<name<<endl;   
  48. }  
  49.   
  50. int main()  
  51. {  
  52.     resume *r1 = new ResumeA("A");  
  53.     resume *r2 = new ResumeB("B");  
  54.     resume *r3 = r1->clone();  
  55.     resume *r4 = r2->clone();  
  56.     r1->show();  
  57.     r2->show();  
  58.     //删除r1,r2  
  59.     delete r1;  
  60.     delete r2;    
  61.     r1 = r2 = NULL;  
  62.     //深拷贝所以对r3,r4无影响  
  63.     r3->show();   
  64.     r4->show();  
  65.     delete r3; delete r4;  
  66.     r3 = r4 = NULL;  
  67.   
  68. }  
上述代码中: ResumeA,ResumeB中的构造函数是只是按照形参重新构建一个新的对象,而clone()会New一个新的对象,所以删除掉r1,r2不会对r3,r4有任何影响!

其实这个设计模式比较简单,我们总结一下具体操作步骤。

1、声明一个抽象基类,并定义clone()函数为纯虚函数。

2、实例化各个子类,并且实现复制构造函数,并实现clone()函数

3、继承抽象基类,如果自己的类中并没有重载构造函数,则为浅复制,重载后在clone()里return New的对象则为深复制,主要还是将引用对象的变量指向新的对象!


好了,估计这篇文章也就我自己能看的懂。哈哈!


友情提示,参考文章:http://blog.csdn.net/lbqbraveheart/article/details/7086883

 参考书籍:大话设计模式







  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值