设计模式 笔记 生成器(建造者)模式 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 ...
随机推荐
- c#经典算法之冒泡排序(Bubble Sort)
转载于:https://www.cnblogs.com/shen-hua/p/5422676.html 原理:比较两个相邻的元素,将值大的元素交换至右端. 思路:依次比较相邻的两个数,将小数放在前面, ...
- 使用 D: 盘作为 Windows VM 上的数据驱动器
如果应用程序需要使用 D 盘存储数据,请按照以下说明使用其他驱动器号作为临时磁盘. 切勿使用临时磁盘来存储需要保存的数据. 如果调整虚拟机大小或停止(解除分配)虚拟机,这可能会触发将虚拟机放置于新虚拟 ...
- RBAC用户角色权限设计方案【转载】
RBAC(Role-Based Access Control,基于角色的访问控制),就是用户通过角色与权限进行关联.简单地说,一个用户拥有若干角色,每一个角色拥有若干权限.这样,就构造成“用户-角色- ...
- .net 操作MongoDB 基础
1. 下载驱动,最好使用 NuGet 下载,直接搜索MongoDB: 2. 引用相关驱动 3. 部分测试代码,主要是针对MongoDB的GridFS 文件存储来用 using Mongo.Model; ...
- 从零起步做到Linux运维经理,你必须管好的23个细节
不想成为将军的士兵,不是好士兵-拿破仑 如何成为运维经理?成为运维经理需要什么样的能力?我想很多运维工程师都会有这样的思考和问题. 如何成为运维经理.一般来说,运维经理大概有两种出身,一种是从底层最基 ...
- python基础学习5----字典
字典由大括号和键值对组成,特点为无序,键唯一 1.字典的创建 #直接创建字典 dic1={'name':'a','age':20} #通过dict创建字典,输出都为{'name': 'a', 'age ...
- How to Be Assertive Asking for What You Want Firmly and Fairly
What Is Assertiveness? It's not always easy to identify truly assertive behavior. This is because th ...
- Active Directory、Exchange、单点登录,企业账号统一管理解决方案
现在的公司一般都会有很多内部管理系统,比如OA.ERP.CRM.邮件系统等.员工入职之后如果每个系统都创建一个账号和密码,首先员工记系统账号就是一件非常头疼的事情,如果公司有一百个系统那就得创建一百个 ...
- mysql workbench中my.ini路径不一样
mysql workbench中的my.ini路径与mysql服务中的路径不一样 删除mysql workbench的配置文件即可解决 win7下的配置文件路径: %APPDATA\MySQL\Wor ...
- beta冲刺————第一天(1/5)
人员的再次分配: 调走人员:陈裕鹏(原来在本队伍主要进行文章推荐算法的设计) 调入人员:陈邡(原Dipper团队,负责游戏内容的策划案,以及做一些后端的探索工作.) 现队员工作划分: 王国华,吴君毅, ...