首页 > 代码库 > 生成器模式(Builder)-- 对象创建型模式

生成器模式(Builder)-- 对象创建型模式

1. 动机

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。一个RTF(Rich Text Format)文档交换格式的阅读器应能将RTF转换为多种正文格式。该阅读器可以将RTF文档转换成普通ASCII文本或转换成一个能以交互方式编辑的正文窗口组件。但问题在于可能转换的数目是无限的。因此要能够很容易实现新的转换的增加,同时却不改变RTF阅读器。其实也就是,前面的数据接卸(源头处理)归解析,后续的显示处理,由显示处理的部分来完成。在数据解析和显示处理之间架设一个标准的桥梁,供两方通知交互。

2. 描述

当RTF Reader对RTF文档进行语法分析时,它使用TextConverter去做转换。无论何时RTF Reader识别了一个RTF标记(或是普通正文或是一个RTF控制字),它都发送一个请求给TextConverter去转换这个标记。TextConverter对象负责进行数据转换以及用特定格式表示该标记。至于具体转换成什么样的显示,完全有实际TextConverter来处理。
    TextConvert的子类对不同转换和不同格式进行特殊处理。例如,一个ASCIIConverter只负责转换普通文本,而忽略其他转换请求。另一方面,一个TeXConverter将会为实现对所有请求的操作,以便生成一个获取正文中所有风格信息的TEX表示。一个TextWidgetConverter将生成一个复杂的用户界面对象以便用户浏览和编辑正文。
    这里有个关键,就是RTF Reader解析出来的Symbol是所有TextConvert都能看的懂的,也许某个TextConvert不一定会去处理这个symbol,他有可能忽略掉这个Symbol,但忽略,也是一种看懂的行为。

image

 

 

image

 

参与者:

  • Builder(TextConvert)

为创建一个Product对象的各个部件制定抽象接口

  • ConcreteBuilder (AsciiConverter、TeXConverter、TextWidgetConverter)

实现Builder的接口,以构造和装配该产品的各个部件

定义并明确它所创建的表示

提供一个检索产品的接口(例如, GetAsciiText和GetTextWidget)

  • Director (RTFReader)

构造一个使用Builder接口的对象

  • Product (AsciiText、TeXText、TextWidget)

表示被构造的复杂对象。ConcreteBuilder创建该铲平的内部表示并定义它的装配过程。

包含定义组成部件的类,包括将这些部件装配成最终产品的接口

image

 

从上图也可以看出, Builder模式除了“生成”的含义外,还强调了通过aDirector来组装所有aConcreteBuilder的过程。

class MazeBuilder {   //这个是Builderpublic:    virtual void BuildMaze() {}    virtual void BuildRoom(int room) {}    virtual void BuildDoor    virtual Maze * GetMaze() {return 0;}protected:    MazeBuilder();};Maze * MazeGame::CreateMaze(MazeBuilder & builder) {   //这个就是Director    builder.BuildMaze();    builder.BuildRoom(1);    builder.BuildRoom(2);    builder.BuildRoom(1, 2);    return builder.GetMaze;}class StanderdMazeBuilder : public MazeBuilder {    //这个是ConcreteBuilderpublic:    StandardMazeBuilder();    virtual void BuildMaze();    virtual void BuildRoom(int);    virtual void BuildDoor(int, int);    virtual Maze * GetMaze();private:    Direction CommonWall(Room *, Room*);    Maze * _currentMaze;};void StandardMazeBuiler::StandardMazeBuilder() {        _currentMaze = 0;}void StandardMazeBuiler::BuildMaze() {    //这是ConcreteBuilder的BuilPartA        _currentMaze = new Maze;};Maze * StandardMazeBuiler::GetMaze() {    //这是ConcreteBuilder的GetResult        Return _currentMaze;}void StandardMazeBuiler::BuildRoom(int n) {    //这是ConcreteBuilder的BuilPartB    Room * room = new Room(n);    room->SetSide(North, new Wall);    room->SetSide(South, new Wall);    room->SetSide(West, new Wall);    room->SetSide(East, new Wall);    _currentMaze->AddRoom(room)}//作为Client:Maze *maze;MazeGame game; //aDirectorStandardMazeBuilder builder; //aConcreteBuilderGame.CreateMaze(builder); //Constructormaze = builder.GetMaze();  //getResult

 

3. 适用性

 

  1. 他使得你可以该表一个产品的内部表示
  2. 它将构造代码和表示代码分开:Builder模式通过封装一个复杂对象的创建和表示方式提高了对象的模块性。客户不需要知道定义产品内部结构的类的所有信息;这些类是不出现在Builder接口中的。每个ConcreteBuilder包含了创建和装配一个特定产品的所有代码。这些代码只需要写一次;然后不同的Director可以复用它以在相同部件集合的基础上构作不同的Product。在前面的RTF例子中,我们可以为RTF格式以外的格式定义一个阅读器,比如一个SGMLReader,并使用相同的TextConverter生成SGML文档的ASCIIText、TeXText和TextWidget译本。
  3. 它使你可对构造过程进行更精细的控制:Builder模式与一下子就生成产品的创建型模式不同,它是在导向者的控制下一步一步构造产品的。仅当该产品完成时导向者才从生成器中取回它。因此Builder接口相比其他创建型模式能更好的反映产品的构造过程。这使你可以更精细的控制构建过程,从而能更精细的控制所得产品的内部结构。