设计模式 笔记 生成器(建造者)模式 Builder
//---------------------------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(){return
;}
protected:
MazeBuilder();
};
//Director,根据传入的Builder创建迷宫
Maze* MazeGame::CreateMaze(MazeBuilder& builder)
{
//这里想怎么创建就怎么创建,无需关注底部实现细节
builder.BuildMaze();
builder.BuildRoom();
builder.BuildRoom();
builder.BuildDoor(,
);
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 =
;
}
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(), _doors()
{
//_rooms = _doors = 0;
应该使用初始化列表初始化
}
inline
void CountingMazeBuilder::BuildRoom(int)
{
++_rooms;
}
inline
void CountingMazeBuilder::BuildDoor(int)
{
++_doors;
}
inline CountingMazeBuilder::GetCounts(int& rooms,
int& doors) const
{
rooms = _rooms;
doors = _doors;
}
//这就是一个计数的builder,感觉如果需要计数,直接放在基类里就行了,
想用的时候调用基类的方法一次就好。
设计模式 笔记 生成器(建造者)模式 Builder的更多相关文章
- 设计模式系列之建造者模式(Builder Pattern)——复杂对象的组装与创建
说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修炼之道)>一书的阅读笔记.个人感觉这本书讲的不错,有兴趣推荐读一读.详细内容也可以看看此书作者的博客https:/ ...
- 【原】iOS设计模式之:建造者模式Builder Pattern,用于改进初始化参数
本文主要讨论一下iOS中的Builder Pattern.与网上很多版本不同,本文不去长篇大论地解释建造者模式的概念,那些东西太虚了.设计模式这种东西是为了解决实际问题的,不能为了设计模式而设计模式, ...
- iOS设计模式之:建造者模式Builder Pattern,用于改进初始化参数
转自:http://www.cnblogs.com/wengzilin/p/4365855.html 本文主要讨论一下iOS中的Builder Pattern.与网上很多版本不同,本文不去长篇大论地解 ...
- IOS设计模式浅析之建造者模式(Builder)
定义 "将一个复杂对象的构建与它的表现分离,使得同样的构建过程可以创建不同的表现". 最初的定义出现于<设计模式>(Addison-Wesley,1994). 看这个概 ...
- Net设计模式实例之建造者模式(Builder Pattern)
一.建造者模式简介(Brief Introduction) 建造者模式(Builder Pattern),将一个复杂对象的构建与它的表示分离,使的同样的构建过程可以创建不同的表示. 建造者模式的优点是 ...
- 设计模式学习之建造者模式(Builder,创建型模式)(6)
假如我们需要建造一个房子,并且我们也不知道如何去建造房子,所以就去找别人帮我们造房子 第一步: 新建一个房子类House,里面有房子该有的属性,我们去找房子建造者接口HouseBuilder,我们要建 ...
- 设计模式—建造者模式(Builder)
title: 设计模式-建造者模式 建造者模式(Builder)是一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,用户不需要知道内部的具体构建细节.建造者模式属于对 ...
- 乐在其中设计模式(C#) - 建造者模式(Builder Pattern)
原文:乐在其中设计模式(C#) - 建造者模式(Builder Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 建造者模式(Builder Pattern) 作者:webabc ...
- 【设计模式】建造者模式 Builder Pattern
前面学习了简单工厂模式,工厂方法模式以及抽象工厂模式,这些都是创建类的对象所使用的一些常用的方法和套路, 那么如果我们创建一个很复杂的对象可上面的三种方法都不太适合,那么“专业的事交给专业人去做”,2 ...
随机推荐
- visual studio 单元测试的认识
单元测试(unit testing),对软件中的最小单元进行检查和验证,其一般验证对象是一个函数或者一个类. Team Test 是 Visual Studio 集成的单元测试框架,它支持: 测试方法 ...
- Angular 服务的简单使用
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- ASP.NET获取服务器信息大全
p>服务器IP:<%=Request.ServerVariables["LOCAL_ADDR"]%></p> <p>服务器名:<%= ...
- Java中字符数组、String类、StringBuffer三者的相互转换
一.StringBuffer与String的相互转换 1.将StringBuffer转换成String StringBuffer类成员toString函数可将其转换成String类型. StringB ...
- Centos7源码安装httpd2.4版本web服务器
我们的系统平台是在centos7.5的环境下安装httpd2.4版本的软件,2.4版本的软件有一个特征就是需要安装arp包以及arp-util包才可以. 1.首先是下载httpd2.4版本的包,以及安 ...
- TIDB单机多实例进程
TIDB节点: TIKV节点(tidb服务也有放在这里也有) tidb进程 tikv进程 当使用单机多实例(就是一个机器多个tikv的存储节点)的时候,每个实例都有对应的一个进程,这个进程号就是我们在 ...
- 面向对象程序设计_Task7_Summary
Summary of the ... 题目链接:第七次作业 终于还是迎来了这学期的最后一次作业,唠叨话还是放最后说,先说说计算器这玩意儿吧 贯穿了整个学期的计算器,要是让我对自己做个评价,顶多只是还好 ...
- Hive 整合Hbase
摘要 Hive提供了与HBase的集成,使得能够在HBase表上使用HQL语句进行查询 插入操作以及进行Join和Union等复杂查询.同时也可以将hive表中的数据映射到Hbase中. 应用 ...
- 小程序报错数据传输长度为 xxx 已经超过最大长度 xxx
这个错误通常在通过base64给images赋值时发生,setData()微信设置的一次最大传输长度为1M,所有如果编码后的base64字符串长度超过了1M就会报这个错误. 如何解决? 我们可以采取曲 ...
- AtCoder Regular Contest
一句话题解 因为上篇AGC的写的有点长……估计这篇也短不了所以放个一句话题解方便查阅啥的吧QwQ 具体的题意代码题解还是往下翻…… ARC 058 D:简单容斥计数. E:用二进制表示放的数字,然后状 ...