设计模式(3) 创建型模式 BUILDER 生成器

目录

本节关于BUILDER 生成器模式 —— 对象创建模式

1. 意图

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示

2. 动机

如下图,一个Rich Text Format文档交换格式的阅读器能将RTF转换为多种正文格式。该阅读器可以将RTF文档转换为ASCII文本或转换为一个能以交互方式编辑的正文窗口组件

问题:转换的数目无穷;需要容易实现新转换的增加,同时不改变RTF阅读器

解决方法:TextConverter对象——将RTF转换为另一种正文表示——配置RTFReader类。其负责进行数据转换以及用特定格式表示该标记。TextConvert的子类对不同转换和不同格式进行特殊处理。

每种转换器类将创建和装配一个复杂对象的机制隐含在抽象接口后面。转换器独立于阅读器,阅读器负责对一个RTF文档进行语法分析。

每一个转换器类在该模式中被称为生成器(builder),而阅读器则称为导向器(director)

3. 适用性

  • 当创建复杂对象的算法应独立于该对象的组成部分以及其装配方式时
  • 当构造过程必须允许被构造的对象有不同的表示

4. 结构

上图的扩展咯

5. 参与者

  • Builder (TextConverter)
    • 为创建一个Product对象的各个部件指定抽象接口
  • ConcreteBuilder (ASCIIConverter, TeXConverter, TextWidgetConverter)
    • 实现Builder的接口以构造和装配该产品的各个部件
    • 定义并明确它所创建的表示
    • 提供一个检索产品的接口(例如GetASCIIText和GetTextWidget)
  • Director (RTFReader)
    • 构造一个使用Builder接口的对象
  • Product (ASCIIText, TeXText, TextWidget)
    • 表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义其装配过程。
    • 包含定义组成部件的类,包括将这些部件装配成最终产品的接口。

6. 协作

Builder和Director交互图

  • 客户创建Director对象,并用它所想要的Builder对象进行配置
  • 一旦产品部件生产,导向器就会通知生成器
  • 生成器处理导向器的请求,并将部件添加到该产品中
  • 客户从生成器中检索产品

7. 效果

  • 它使你可以改变一个产品的内部实现
  • 它可以将构造代码和表示代码分开
  • 它使你可对构造过程进行更精细的控制

8. 实现

通常有一个抽象的Builder类为导向者可能要求创建的每一个构件定义一个操作。这些操作缺省情况下什么都不做。一个ConcreBuilder类对它有兴趣创建的构件重定义这些操作。

  • 装配和构造接口
  • 为什么产品没有抽象类
  • 在Builder中缺省的方法为空

9. 代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
class MazeBuilder {   //这个是Builder
public:
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 { //这个是ConcreteBuilder
public:
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; //aDirector
StandardMazeBuilder builder; //aConcreteBuilder

Game.CreateMaze(builder); //Constructor
maze = builder.GetMaze(); //getResult

10. 已知应用

RTF转换器应用来自来自ET++

11. 相关模式

Abstract Factory与Builder相似,因为它也可以创建复杂对象。

主要区别是Builder着重于一步步构造一个复杂对象Abstract Factory着重于多个系列产品对象构造

0%