设计模式6——创建型模式之原型模式

定义:原型模式(Prototype Pattern),用原型模式指定创建对象的种类,并且通过拷贝这些原型创建新的对象。

类型:创建型模式。

类图

 

参与角色:

  1. CPrototype,抽象原型基类,提供一个Clone的接口以及一些设置显示的接口。
  1. CConcretePrototype,声明定义原型的相关参数,并实现Clone接口,主要是通过实现拷贝构造函数来完成的。

另外实现其他接口。

  1. Client,首先定义一个原型对象,然后以此为原型克隆新的对象。

概述:

        如果只是为了更快的完成新对象的生成,其实就没必要使用原型模式了。因为可以直接使用拷贝构造函数即可。而使用原型模式最重要的原因是隔离Client去了解具体的实现类,降低模块间的耦合。Client只需要知道一个抽象类的指针,不仅可以操作具体各咱方法,另外也还可以生成新的对象。

        另外,使用拷贝构造函数时,需要注意深拷贝及浅拷贝。浅拷贝,即按位进行拷贝,即两个对象的每一个成员变量是相同的。深拷贝,自定义拷贝,一般会处理指针,引用等类型,保证它们有相同的值,而不是它们本身相同。

        有一批Thinkpad电脑,除了内存和硬盘容量外,其他配置都相同。我们可以通过原型对象生成新的对象,并且不需要知道具体的实现类名。

 

// 提供接口

 1 class CPrototype
 2 
 3 {
 4 
 5 public:
 6 
 7     virtual CPrototype* Clone() = 0;
 8 
 9     virtual void Show() = 0;
10 
11     virtual void SetRam(int _nRam) = 0;
12 
13     virtual void SetRom(int _nRom) = 0;
14 
15 };

 

// 电脑的基本配置信息类

  1 class CComputerConfig : public CPrototype
  2 
  3 {
  4 
  5 public:
  6 
  7     CComputerConfig(char* _szName, int _nRomSize, int _nRamSize) : m_nRomSize(_nRomSize), m_nRamSize(_nRamSize)
  8 
  9     {
 10 
 11         if (NULL != _szName)
 12 
 13         {
 14 
 15             size_t nSize = strlen(_szName) + 1;
 16 
 17             m_szComputerName = new char[nSize];
 18 
 19             strcpy_s(m_szComputerName, nSize, _szName);
 20 
 21         }
 22 
 23         else
 24 
 25         {
 26 
 27             m_szComputerName = NULL;
 28 
 29         }
 30 
 31     }
 32 
 33  
 34 
 35     ~CComputerConfig()
 36 
 37     {
 38 
 39         if (NULL != m_szComputerName)
 40 
 41         {
 42 
 43             delete m_szComputerName;
 44 
 45         }
 46 
 47     }
 48 
 49  
 50 
 51     CComputerConfig(const CComputerConfig& _other)
 52 
 53     {
 54 
 55         if (NULL == _other.m_szComputerName)
 56 
 57         {
 58 
 59             m_szComputerName = NULL;
 60 
 61         }
 62 
 63         else
 64 
 65         {
 66 
 67             size_t nSize = strlen(_other.m_szComputerName) + 1;
 68 
 69             m_szComputerName = new char[nSize];
 70 
 71             strcpy_s(m_szComputerName, nSize, _other.m_szComputerName);
 72 
 73  
 74 
 75             m_nRomSize = _other.m_nRomSize;
 76 
 77             m_nRamSize = _other.m_nRamSize;
 78 
 79         }
 80 
 81     }
 82 
 83  
 84 
 85     virtual CPrototype* Clone()
 86 
 87     {
 88 
 89         return new CComputerConfig(*this);
 90 
 91     }
 92 
 93  
 94 
 95     virtual void Show()
 96 
 97     {
 98 
 99         cout<<m_szComputerName<<",Ram "<<m_nRamSize<<",Rom "<<m_nRomSize<<endl;
100 
101     }
102 
103  
104 
105     virtual void SetRam(int _nRam)
106 
107     {
108 
109         m_nRamSize = _nRam;
110 
111     }
112 
113  
114 
115     virtual void SetRom(int _nRom)
116 
117     {
118 
119         m_nRomSize = _nRom;
120 
121     }
122 
123 public:
124 
125     char* m_szComputerName;
126 
127     int m_nRomSize;
128 
129     int m_nRamSize;
130 
131 };
132 
133  

 

// 客户端

 1 int _tmain(int argc, _TCHAR* argv[])
 2 
 3 {
 4 
 5     // ThindPad系列电脑
 6 
 7     CComputerConfig computer("Thinkpad", 500, 2);
 8 
 9  
10 
11     // 原型
12 
13     CPrototype* pPrototype = &computer;
14 
15     pPrototype->Show();
16 
17  
18 
19     // ThindPad系列的2G内存版,500G硬盘版
20 
21     CPrototype* p2GComputer = computer.Clone();
22 
23     p2GComputer->SetRam(4);
24 
25     p2GComputer->Show();
26 
27  
28 
29     // 4G内存,1T硬盘版
30 
31     CPrototype* p1TCompter = computer.Clone();
32 
33     p1TCompter->SetRam(8);
34 
35     p1TCompter->SetRom(1024);
36 
37     p1TCompter->Show();
38 
39  
40 
41 return 0;
42 
43 }
44 
45  

 

使用场合

  1. 两个模块A,B,模块B对外暴露一个对象C指针。而模块A需要建立很多很多C的对象,但是不需要知道具体的C是如何创建的。这个时候就应该使用原型模式。

优缺点

  1. 优点,能够降低模块间的耦合性,另外能够快速的创建新对象。

缺点,改造一个已有类型时,需要细心考虑所有成员变量拷贝的问题,容易遗漏造成错误。

参考资料

  1. 《设计模式——可复用面向对象软件基础》
  2. 《Java与模式》
  3. 《大话设计模式》
posted @ 2014-01-10 15:18  飞鹤0755  阅读(304)  评论(0编辑  收藏  举报