您的位置:首页 > 其它

设计模式(4) - Prototype原型模式

2013-12-22 00:05 330 查看

1. 意图

原型模式可以让我们在创建新的实例时,隐藏内部复杂性。

用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。Prototype模式提供了一个通过已存在对象进行新对象创建的接口(Clone), Clone()实现和具体的语言相关,在C++中通过拷贝构造函数实现。

2. UML类图



3. 代码实现

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

using namespace std;
const int N = 4;

// Prototype
class Document
{
public:
virtual Document* clone() const = 0;
virtual void store() const = 0;
virtual ~Document() { }
};

// Concrete prototype : xmlDoc, plainDoc, spreadsheetDoc
class xmlDoc : public Document
{
public:
Document* clone() const
{ return new xmlDoc; }
void store() const
{ cout<<"xmlDoc"<<endl; }
public:
xmlDoc()
{ cout<<"xmlDoc constructor"<<endl;}
~xmlDoc()
{ cout<<"xmlDoc destructor"<<endl;}
};

class plainDoc : public Document
{
public:
Document* clone() const
{ return new plainDoc; }
void store() const
{ cout<<"plainDoc"<<endl; }
public:
plainDoc()
{ cout<<"plainDoc constructor"<<endl;}
~plainDoc()
{ cout<<"plainDoc destructor"<<endl;}
};

class spreadsheetDoc : public Document
{
public:
Document* clone() const
{ return new spreadsheetDoc; }
void store() const
{ cout<<"spreadsheetDoc"<<endl; }
public:
spreadsheetDoc()
{ cout<<"spreadsheetDoc constructor"<<endl;}
~spreadsheetDoc()
{ cout<<"spreadsheetDoc destructor"<<endl;}
};

// generateDocument() calls Concrete Prototype's clone() method
// inherited from base class Prototype
class DocumentManager
{
public:
static Document* generateDocument(int choice);
DocumentManager()
{ cout<<"DocumentManager constructor"<<endl; }
~DocumentManager()
{ cout<<"DocumentManager destructor"<<endl; }
private:
static Document* _docTypes
;
};

Document* DocumentManager::_docTypes[] = {0, new xmlDoc, new plainDoc, new spreadsheetDoc};

Document* DocumentManager::generateDocument(int choice)
{
return _docTypes[choice]->clone();
}

//for_each op()
class DestructClasses
{
public:
void operator()(Document *doc) const
{  delete doc; }
public:
DestructClasses()
{ cout<<"DestructClasses constructor"<<endl; }
~DestructClasses()
{ cout<<"DestructClasses destructor"<<endl; }
};

//client
int main()
{
std::vector<Document*> docs(N);

int choice=0;
cout<<"quit(0), xml(1), plain(2), spreadsheet(3): "<<endl;
while(true)
{
cout<<"Type in your choice (0-3)"<<endl;
cin>>choice;

if(choice<=0 || choice>=N)
break;

docs[choice] = DocumentManager::generateDocument(choice);
}

cout<<"\nvector elements print"<<endl;
for(int i=0; i<docs.size(); ++i)
if(NULL!=docs[i])
docs[i]->store();
cout<<endl;

DestructClasses dc;
for_each(docs.begin(), docs.end(), dc);

system("pause");
return 0;
}
运行结果为:

xmlDoc constructor
plainDoc constructor
spreadsheetDoc constructor
quit(0), xml(1), plain(2), spreadsheet(3):
Type in your choice (0-3)
1
xmlDoc constructor
Type in your choice (0-3)
2
plainDoc constructor
Type in your choice (0-3)
3
spreadsheetDoc constructor
Type in your choice (0-3)
0

vector elements print
xmlDoc
plainDoc
spreadsheetDoc

DestructClasses constructor
xmlDoc destructor
plainDoc destructor
spreadsheetDoc destructor
DestructClasses destructor
DestructClasses destructor
Press any key to continue . . .
DestructClasses destructor
由上面结果可知:

1). 3个原始对象定义为静态对象,在数组_docTypes中生成。

2).创建新的对象在clone函数中完成。注意:每种类型只能输入一次,会保存在vector中,会被析构。但是如果输入多次相同类型的值,会new出来多个对象,并且只会析构最后new出来的那个对象,前面的对象没有析构,会有内存泄漏。

3).本文重点在于说明Prototype模式,而不再于新对象的生成方式方法。

4).第26,27行是在for_each中的析构调用,第29行,是在程序退出之前,系统回收局部变量dc的内存,因而调用了其析构函数。

4. 总结

Prototype模式和Builder模式、AbstractFactory模式都是通过一个类(对象实例)来专门负责对象的创建工作(工厂对象),它们之间的区别是:Builder模式重在复杂对象的一步步创建(并不直接返回对象),AbstractFactory模式重在产生多个相互依赖类的对象,而Prototype模式重在从自身复制自己创建新类。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: