//---------------------------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的更多相关文章

  1. 设计模式系列之建造者模式(Builder Pattern)——复杂对象的组装与创建

    说明:设计模式系列文章是读刘伟所著<设计模式的艺术之道(软件开发人员内功修炼之道)>一书的阅读笔记.个人感觉这本书讲的不错,有兴趣推荐读一读.详细内容也可以看看此书作者的博客https:/ ...

  2. 【原】iOS设计模式之:建造者模式Builder Pattern,用于改进初始化参数

    本文主要讨论一下iOS中的Builder Pattern.与网上很多版本不同,本文不去长篇大论地解释建造者模式的概念,那些东西太虚了.设计模式这种东西是为了解决实际问题的,不能为了设计模式而设计模式, ...

  3. iOS设计模式之:建造者模式Builder Pattern,用于改进初始化参数

    转自:http://www.cnblogs.com/wengzilin/p/4365855.html 本文主要讨论一下iOS中的Builder Pattern.与网上很多版本不同,本文不去长篇大论地解 ...

  4. IOS设计模式浅析之建造者模式(Builder)

    定义 "将一个复杂对象的构建与它的表现分离,使得同样的构建过程可以创建不同的表现". 最初的定义出现于<设计模式>(Addison-Wesley,1994). 看这个概 ...

  5. Net设计模式实例之建造者模式(Builder Pattern)

    一.建造者模式简介(Brief Introduction) 建造者模式(Builder Pattern),将一个复杂对象的构建与它的表示分离,使的同样的构建过程可以创建不同的表示. 建造者模式的优点是 ...

  6. 设计模式学习之建造者模式(Builder,创建型模式)(6)

    假如我们需要建造一个房子,并且我们也不知道如何去建造房子,所以就去找别人帮我们造房子 第一步: 新建一个房子类House,里面有房子该有的属性,我们去找房子建造者接口HouseBuilder,我们要建 ...

  7. 设计模式—建造者模式(Builder)

    title: 设计模式-建造者模式 建造者模式(Builder)是一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,用户不需要知道内部的具体构建细节.建造者模式属于对 ...

  8. 乐在其中设计模式(C#) - 建造者模式(Builder Pattern)

    原文:乐在其中设计模式(C#) - 建造者模式(Builder Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 建造者模式(Builder Pattern) 作者:webabc ...

  9. 【设计模式】建造者模式 Builder Pattern

    前面学习了简单工厂模式,工厂方法模式以及抽象工厂模式,这些都是创建类的对象所使用的一些常用的方法和套路, 那么如果我们创建一个很复杂的对象可上面的三种方法都不太适合,那么“专业的事交给专业人去做”,2 ...

随机推荐

  1. C#中virtual(虚方法)的理解以及和abstract(抽象方法)的区别

    Virtual方法(虚方法) virtual 关键字用于在基类中修饰方法.virtual的使用会有两种情况: 情况1:在基类中定义了virtual方法,但在派生类中没有重写该虚方法.那么在对派生类实例 ...

  2. MSSQL段落还原脚本

    --段落还原:数据库损坏范围比较大,跨多个数据文件甚至跨文件组的时候,我们不得不恢复整个数据库.--这时如果数据库特别大,数据库恢复时间将会很长.但我们可以使用SQL Server提供的段落还原,来逐 ...

  3. UNIX高级环境编程(12)进程关联(Process Relationships)- 终端登录过程 ,进程组,Session

    在前面的章节我们了解到,进程之间是有关联的: 每个进程都有一个父进程: 子进程退出时,父进程可以感知并且获取子进程的退出状态. 本章我们将了解: 进程组的更多细节: sessions的内容: logi ...

  4. Window10 Linux子系统挂载磁盘

    默认情况下, Linux子系统将当前winodws磁盘的盘全部挂载到/mnt/<disk_label>, 但一些新增的盘就需要手动做下了.. 官方参考文档 挂载磁盘 -- DrvFs 挂载 ...

  5. Windows 7 任务栏图标消失(变透明,仍然占有地方,但是点击无反应)的解决方法

    解决方案:清理资源管理器缓存(重启资源管理器) 1.打开程序管理器(ctrl+shift+esc) 2.在进程那里找到"explorer.exe",然后按结束进程 3.然后在文件( ...

  6. Linux清除用户登录记录和命令历史方法(个人笔记)

    清除登陆系统成功的记录 [root@localhost root]# echo > /var/log/wtmp //此文件默认打开时乱码,可查到ip等信息 [root@localhost roo ...

  7. SHGetFileInfo 报错 异常 问题

    查看代码是否使用了 ::CoInitializeEx(NULL, COINIT_MULTITHREADED); 如果是,换成在每个线程调用 ::CoInitialize(NULL); 真够蛋疼的,查了 ...

  8. 【9】python关于os模块与os.path的相关操作

    ---恢复内容开始--- #__author:"吉*佳" #date: 2018/10/20 0020 #function: # os模块知识点 import os # 获取平台名 ...

  9. PyQt5---ChangeIcon

    # -*- coding:utf-8 -*- ''' Created on Sep 13, 2018 @author: SaShuangYiBing ''' import sys from PyQt5 ...

  10. vultr vps(ubuntu)忘记密码

    参考官方解决方案:https://www.vultr.com/docs/boot-into-single-user-mode-reset-root-password 在此仅给出ubuntu下的解决 D ...