本帖最后由 Chenxs110 于 2012-8-21 21:45 编辑
Builder 构建者模式
1.意图
将一个复杂对象的构建与它的表示相分离,使得同样的构建过程可以创建不同的表示.
2.动机
考虑一个RTF(Rich Text Format--有字符有图片等)文档交换格式的阅读器能够将RTF转换为多种正文格式.该阅读器去可以将RTF
文档转换成普通的ASCII文本或者转换成一个能以交互方式编辑的正文窗口组件.但问题在于可能转换的数目是无限的.因此要能够
很容易实现新的转换的增加,同时确不改变RTF阅读器.
一个解决办法是用一个可以将RTF转换成另一种正文表示的TextConverter对象配置这个RTFReader类.当RTFReader对RTF文档
进行语法分析时,它使用TextConverter去做转换.无论何时RTFReader识别了一个RTF标记(有可能是普通的正文也可能是i一个RTF
控制字).它都发送一个请求给TextConverter去转换这个标记.TextConverter对象负责数据转换以及用特定格式表示该标记.
UML图如下:
RTFReader负责指定创建方针.比如遇到了CHAR就用ASCIIConverter转换为ASCIIText,遇到了FONT就是要改变字体了,就调用TeXConveter
进行字体转换.遇到PARA就调用TextWidgetConveter进行TextWidget转换.在这里RTFReader就好像是一个指挥者.它决定了构建的过程和
方式.
Builder模式描述了所有这些关系.每一个转换器Converter类在该模式中被称为生成器(Builder).而阅读器则称为指挥者(director).在上面的
例子中,Builder模式将分析文本格式的算法与描述怎样创建和表示一个转换后格式的算法分离开来(将构建与表示相分离).这使得我们可以
重用RTFReader中的语法分析算法.根据RTF文档创建不同的正文表示----仅需使用不同的TextConverter的子类配置RTFReader即可.
3.适用范围
<1>当创建复杂对象的算法应该独立于该对象的组成部分以及他们的装配方式时
<2>当构建过程必须允许被构建的对象有不同表示时
4.结构图
5.实现
考虑这样一个程序,它可以把编辑框选中的区域生成不同格式的图像文件.这里以bmp和jpeg做例子.我们把图像的构造过程简化为BuildArea
和BuildContainer两个方法.客户端使用的时候它只想创建一定格式的图片文件.但是对图片怎么创建,格式有什么不同肯定不感兴趣(这也是设计
模式的一个原则---单一责任).
这里我们可以定义一个父类PictureBuilderclass PictureBuilder
{
public:
virtual void BuildContainer() = 0;
virtual void BuildArea() = 0;
PictureBuilder();
virtual ~PictureBuilder();
};
针对两种不同形式的实现,我们分别让JPEGPictureBuilder和BMPPictureBuilder父类PictureBuilderclass JPEGPictureBuilder : public PictureBuilder
{
public:
virtual void BuildContainer();
virtual void BuildArea();
JPEGPictureBuilder();
virtual ~JPEGPictureBuilder();
};
class BMPPictureBuilder : public PictureBuilder
{
public:
void BuildContainer();
void BuildArea();
BMPPictureBuilder();
virtual ~BMPPictureBuilder();
};
然后分别实现各自的负责构建过程的虚函数void JPEGPictureBuilder::BuildArea()
{
cout<<"Build JPEG Picture Area"<<endl;
}
void JPEGPictureBuilder::BuildContainer()
{
cout<<"Build JPEG Picture Container"<<endl;
}
void BMPPictureBuilder::BuildArea()
{
cout<<"Build BMP Picture Area"<<endl;
}
void BMPPictureBuilder::BuildContainer()
{
cout<<"Build BMP Picture Container"<<endl;
}
接下来是我们的指挥者类PictureDirector的定义class PictureDirector
{
public:
void CreateFile();
PictureDirector(PictureBuilder * pb);
virtual ~PictureDirector();
private:
PictureBuilder * pb;
};
构造方法相应的修改了一下,因为我们的指挥者要知道它当前指挥的对象.
构造方法,直接赋值就好了.另外添加一个CreateFile方法.改方法内部调用各个构建过程PictureDirector::PictureDirector(PictureBuilder * pb)
{
this->pb = pb;
}
PictureDirector::~PictureDirector()
{
}
void PictureDirector::CreateFile()
{
pb->BuildArea();
pb->BuildContainer();
}
接下来看客户端的实现#include "BMPPictureBuilder.h"
#include "JPEGPictureBuilder.h"
#include "PictureDirector.h"
int main()
{
PictureBuilder * jpeg = new JPEGPictureBuilder();
PictureBuilder * bmp = new BMPPictureBuilder();
PictureDirector * djpeg = new PictureDirector(jpeg);
djpeg->CreateFile();
PictureDirector * dbmp = new PictureDirector(bmp);
dbmp->CreateFile();
return 1;
}
客户端代码很简单.很好的将文件的表示与构建过程分离了.
|