设计模式 笔记 生成器(建造者)模式 Builder
来源:互联网 发布:产品系统php设计案例 编辑:程序博客网 时间:2024/04/30 15:31
//---------------------------15/04/08----------------------------
//builder 生成器(建造者)模式---对象创建型模式
/*
1:意图:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
2:动机
3:适用性:
1>当创建复杂对象的算法应该独立于该对象的组成部分以及他们的装配方式时。
2>当构造过程必须允许被构造的对象有不同的表示时。
4:结构:
Director:
builder----------------------------->Builder:
Construct() BuildPart()
{ for all objects in structure |
{ builder->BuildPart()} } |
ConcreteBuilder: - - - ->Product
BuildPart()
GetResult()
5:参与者:
1>Builder:为创建一个Product对象的各个部件指定抽象接口。
2>ConcreteBuilder:
1)实现Builder的接口以构造和装配该产品的各个部件。
2)定义并明确它所创建的表示。
3)提供一个检索产品的接口.
3>Director:构造一个使用Builder接口的对象。
4>Product:
1)表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程。
2)包含定义组成部件的类,包括将这些部件装配成最终产品的接口。
6:协作:
1>客户创建Director对象,并用它所想要的Builder对象进行配置。
2>一旦产品部件被生成,导向器就会通知生成器。
3>生成器处理导向器的请求,并将部件添加到该产品中。
4>客户从生成器中检索产品。(得到产品)
下面的图说明了Builder和Director和客户的协作:
aClient aDirector aConcreteBuilder
| | |
new ConcreteBuilder---------------------------->|
new Director(aCon..)--->| |
| | |
Construct()------------>|BuildPartA()---------->|
| BuildPartB()----------->|
| BuildPartC()----------->|
| | |
GetResult()------------------------------------>|
| | |
7:效果:
1>它使你可以改变一个产品的内部表示。
Builder给Director只提供了抽象接口,隐藏了内部装配过程,所以想要改变
内部表示的时候,只需要定义一个新的Builder就行了。
2>它将构造代码和表示代码分开。
ConcreteBuilder已经提供了创建一个产品的所有代码,不同的Director可以复用它
以在相同部件集合的基础上构造不同的Product。
3>它使你可以对构造过程进行更精密的控制。
与一下子就生产产品的创建型模式不同,Builder模式是在导向者的控制下一步一步构造产品的。
所以可以更精细地控制构造过程。
8:实现:
1>要有一个抽象的Builder类为Director提供产品每一个部分创建的接口。ConcreteBuilder
只用对感兴趣的部分实现操作就行。
2>装配和构造接口:Builder类的接口必须足够普遍。
有一个需要考虑的点是,Builder创建PartB时可能需要用到PartA的对象,
所以,可以从PartA那里返回一个PartA对象,再由Director传入PartB。
3>为什么产品没有抽象类:一般生存器生成的产品的表示相差十分之大,以至于难以提供公共父类。
9:代码示例: */
//定义一个抽象类,接口都是空操作,不声明成纯虚函数是因为ConcreteBuilder只需要实现自己感兴趣的接口
class MazeBuilder
{
public:
virtual void BuildMaze(){}
virtual void BuildRoom(int room) {}
virtual void BuildDoor(int roomFrom,int roomTo){}
virtual Maze* GetMaze(){return0;}
protected:
MazeBuilder();
};
//Director,根据传入的Builder创建迷宫
Maze* MazeGame::CreateMaze(MazeBuilder& builder)
{
//这里想怎么创建就怎么创建,无需关注底部实现细节
builder.BuildMaze();
builder.BuildRoom(1);
builder.BuildRoom(2);
builder.BuildDoor(1,2);
return builder.GetMaze();
}
class StandardMazeBuilder :public MazeBuilder
{
public:
StandardMazeBuilder();
virtual void BuildMaze();
virtual void BuildRoom(int);
virtual void BuildDoor(int,int);
virtual Maze* GetMaze();
private:
Direction CommonWall(Room*, Room*);
Maze* _currentMaze;
};
//具体的builder
StandardMazeBuilder::StandardMazeBuilder()
{
_currentMaze =0;
}
void StandardMazeBuilder::BuildMaze()
{
_currentMaze =new Maze;
}
Maze* StandardMazeBuilder::GetMaze()
{
return _currentMaze;
}
void StandardMazeBuilder::BuildRoom(int n)
{
if(!_currentMaze->RoomNo(n))
{
Room* room =new Room(n);
_currentMaze->AddRoom(room);
room->SetSide(North,new Wall);
room->SetSide(South,new Wall);
room->SetSide(East,new Wall);
room->SetSide(West,new Wall);
}
}
void StandardMazeBuilder::BuildDoor(int n1,int n2)
{
Room* r1 = _currentMaze->RoomNo(n1);
Room* r2 = _currentMaze->roomNo(n2);
Door* d =new Door(r1, r2);
r1->SetSide(CommonWall(r1,r2), d);
r2->SetSide(CommonWall(r2,r1), d);
}
//如果我们需要有个个会爆炸的门可以如下实现。
void StandardMazeBuilder::BuildBoomedDoor(int n1,int n2)
{
Room* r1 = _currentMaze->RoomNo(n1);
Room* r2 = _currentMaze->roomNo(n2);
Door* d =new BoomedDoor(r1, r2);
r1->SetSide(CommonWall(r1,r2), d);
// 感觉CommonWall实现为room的成员函数更好,r1.CommonWall(r2)这样更好理解
r2->SetSide(CommonWall(r2,r1), d);
}
//十分简单
Maze* maze;//Product
MazeGame game;//Director
StandardMazeBuilder builder;//Builder
game.CreateMaze(builder);
maze = builder.GetMaze();
//上面的两句可以合并成:
maze = game.CreateMaze(builder);//因为create的实现里已经调用GetMaze了
class CountingMazeBuilder :public MazeBuilder
{
public:
CountingMazeBuilder();
virtual void BuildMaze();
virtual void BuildRoom(int);
virtual void BuildDoor(int,int);
virtual void AddWall(int, Director);
void GetCounts(int&,int&) const;
private:
int _doors;
int _rooms;
};
CountingMazeBuilder::CountingMazeBuilder():_rooms(0), _doors(0)
{
//_rooms = _doors = 0; 应该使用初始化列表初始化
}
inlinevoid CountingMazeBuilder::BuildRoom(int)
{
++_rooms;
}
inlinevoid CountingMazeBuilder::BuildDoor(int)
{
++_doors;
}
inline CountingMazeBuilder::GetCounts(int& rooms,int& doors) const
{
rooms = _rooms;
doors = _doors;
}
//这就是一个计数的builder,感觉如果需要计数,直接放在基类里就行了,想用的时候调用基类的方法一次就好。
- 设计模式 笔记 生成器(建造者)模式 Builder
- 设计模式之建造者模式(生成器模式、Builder)摘录
- 建造者模式 - Builder 生成器模式
- 生成器/建造者模式(Builder Pattern)
- builder(生成器/建造者模式)
- 设计模式之建造者模式(生成器模式)(Builder) 创建型模式
- 【设计模式】建造者(生成器)
- Builder(建造者)设计模式
- 设计模式---建造者模式(Builder)模式
- (六)二十三中设计模式之我见------------建造者模式或生成器模式(Builder Pattern)
- 设计模式学习——建造者模式(Builder Pattern)/生成器模式
- 读书笔记_java设计模式深入研究 第四章 生成器模式 (建造者模式) Builder
- 第六篇、创建型设计模式——建造者(Builder)模式/生成器模式
- 设计模式学习笔记(十二)—Builder建造者模式
- 设计模式笔记17:建造者模式(Builder Pattern)
- 设计模式学习笔记——建造者(Builder)模式
- android生成器模式(建造者模式),builder模式
- 设计模式(4)-建造者模式(Builder)
- Ubuntu 休眠后启动时无声音
- ios7与ios8并存,注册推送通知
- c#
- c语言中如何生成1个0到1的随机数
- MFC中获取当前工作路径与可执行文件路径(转)
- 设计模式 笔记 生成器(建造者)模式 Builder
- 最大子序列、最长递增子序列、最长公共子串、最长公共子序列、字符串编辑距离
- 监听UITextField输入内容的简单实现
- 如何将MongoDB做一项windows服务启动
- 解决 Failed to fetch URL https://dl-ssl.google.com 的问题
- crontab不能正常执行的五种原因
- 指针数组做函数形参
- IntelliJ IDEA的VM parameters的设置
- IOS8 UIAlertController 提示框