[学习笔记]设计模式之Builder
写在前面
为方便读者,本文已添加至索引:
设计模式
学习笔记索引
作为一个新入职的魔导士呢,哦不,是程序员,我以为并没有太多机会去设计项目的软件架构。但是,工作一段时间之后,自己渐渐意识到,哪怕是自己要去做的小feature,也是需要去好好设计。我就应该做好它的架构师。看过一些牛人的文章后,总算意识到自己应该好好学习下设计模式。尽管并不是为了把设计模式作为教条式的方案套用到现实的工作中去,起码我也要做到心中有佛吧,...是心中有数,再在日后工作中积累经验,达到融汇贯通的境地。设计模式是前人总结出的相当重要的经验,也是针对特定问题的简洁而优雅的解决方案。我想,它们不仅在面向对象(OO)设计中极具参考价值,更能推广到日常生活方方面面。因此,我还是好好地学习下设计模式,在此记录自己的学习笔记。废话不多说,开始第一篇:Builder模式。
要点梳理
- 目的分类
- 对象创建型模式
- 范围准则
- 对象
- 主要功能
- 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
- 适用情况
- 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时;
- 当构造过程必须允许被构造的对象有不同的表示时;
- 参与部分
- Builder:为创建一个Product对象的各个部件指定抽象接口
- ConcreteBuilder:具体实现Builder的接口以构造和装配该产品的各个部件的生成器;定义并明确它所创建的表示;提供一个返回检索其Product的接口
- Director:使用Builder接口的对象,称为导向器
- Product:它表示被构造的复杂对象;包含定义组成部件的类,包括将这些部件装配成最终产品的接口。
- 协作过程
- 我们首先创建Director对象,并用它所想要的Builder对象进行配置
- 一旦Product部件被生成,导向器就会通知生成器
- 生成器处理导向器的请求,并将部件添加到该Product中
- 我们可以通过生成器检索最后成品
示例分析 - 世界创造器
总觉得书上讲的例子会否太过严肃,我在这里还是祭出时の魔导士(Mage)的大杀器,神奇的“世界创造器”--WorldCreator吧!平行世界的概念想必大家都懂,现在让我们来看看,Mage如果要用咒语createWorld来生成一个平行世界,让可爱的白雪公主和7个霍比特人幸福快乐地生活,我们从哪开始呢?(貌似混进了奇怪的事情。)那就让我们从WorldCreator类开始吧,它定义了以下接口来创造世界:
class WorldCreator {
public:
virtual void createWorld() {}
virtual void createMountains(int m) {}
virtual void createPlants(int p) {}
virtual void createBuildings(int b) {}
virtual World* getWorld() { return ; }
protected:
WorldCreator();
};
首先建立一个平行世界,然后造山,造树,造房子,嗯......咦,怎么都是virtual?没错!WorldCreator就是前文所提的Builder,它自己并不实际用来创造世界,而是由它的子类来完成;它的主要目的仅仅是为创造世界提供接口,并且,这些接口缺省操作虽然是空,什么也不做,但也不定义成纯虚函数。因为这样便于子类只重定义它们所感兴趣的那些方法。比方说,我突然又想创造一个许多元素生物存在的世界,那里压根没有人工建筑Buildings,那么我就不用重写createBuildings方法了。后面会继续讲到。
有了WorldCreator,我们来看看Mage的createWorld咒语(圈内术语应该叫Mage类的createWorld成员函数)到底是什么样的吧:
World* Mage::createWorld(WorldCreator& builder) {
builder.createWorld();
builder.createMountains();
builder.createPlants();
builder.createBuildings(); return builder.getWorld();
}
像其他创建型模式一样,Builder模式封装了对象是如何被创建的,在这个例子中是通过WorldCreator所定义的接口来封装的。这就意味着我们的Mage可以重用WorldCreator来创造不同种类的世界,比方说,前面提到的没有人工建筑的世界:
World* Mage::createEarthElementalWorld(WorldCreator& builder) {
builder.createWorld();
builder.createMountains(); return builder.getWorld();
}
什么?连树都没有,这地方白雪公主可不想去。
前面说过WorldCreator本身并不能创造世界,因为它是虚的,它的子类才做了实际的工作。来看一个简单的子类LovelyWorldCreator实现:
class LovelyWorldCreator : public WorldCreator {
public:
LovelyWorldCreator() { _currentWorld = ; } virtual void createWorld();
virtual void createMountains(int);
virtual void createPlants(int);
virtual void createBuildings(int); virtual World* getWorld() { return _currentWorld; }
private:
World* _currentWorld;
}; void LovelyWorldCreator::createWorld() {
_currentWorld = new World();
} void LovelyWorldCreator::createMountains(int m) {
if ( !_currentWorld->hasMountains(m) ) {
Mountains* mountains = new Mountains(m);
_currentWorld->addMountains(mountains);
}
} void LovelyWorldCreator::createPlants(int p) {
if ( !_currentWorld->hasPlants(p) ) {
Plants* plants = new Plants(p);
_currentWorld->addPlants(plants);
}
} void LovelyWorldCreator::createBuildings(int b) {
if ( !_currentWorld->hasBuildings(b) ) {
Buildings* buildings = new Buildings(b);
_currentWorld->addBuildings(buildings);
}
}
LovelyWorldCreator
这里createWorld先创造了一个空的世界,然后createMountains, createPlants, createBuildings 分别为这可爱的世界添加了山、树以及建筑物。现在,Mage终于可以用createWorld和LovelyWorldCreator来创造一个平行世界了:
Mage I;
LovelyWorldCreator spell;
World* world = I.createWorld(spell);
美丽的白雪公主如愿以偿地住进了可爱的世界。当然,还有那些霍比特人们。
特点总结
啊,对了,差点忘了说,正因为我们采用了Builder模式(似乎刚跑题了会,赶紧拉回来),将World的构建从World本身的构造函数中分离出来,由WorldCreator封装了统一的创造过程,但是却能通过子类比如LovelyWorldCreator等来创造不同表现形式。这正是Builder设计模式的特点之一。总结说来,Builder模式有如下几个特点:
- 它使我们可以改变一个产品的内部表示。由于Builder对象提供的是一个抽象接口,这个接口可以使生成器隐藏这个产品的表示和内部结构。所以如果要改变产品的内部结构,只需定义一个新的生成器。
- 它将构造代码和表示代码分开。Builder模式通过封装一个复杂对象的创建和表示方式提高了对象的模块性。每个ConcreteBuilder包含了创建和装配一个特定产品的所有代码。这些代码只需要写一次;然后不同的Director可以复用它以在相同部件集合的基础上构作不同的Product。
- 它使我们可以对构造过程进行更精细的控制。Builder模式是在导向者的控制下一步一步构造产品的,仅当该产品完成时导向者才从生成器中取回它。因此Builder相比其他创建型模式能更好的反映产品的构造过程。
写在最后
今天的笔记就到这里了,欢迎大家批评指正!如果觉得可以的话,好文推荐一下,我会非常感谢的!
[学习笔记]设计模式之Builder的更多相关文章
- [学习笔记]设计模式之Abstract Factory
写在前面 为方便读者,本文已添加至索引: 设计模式 学习笔记索引 在上篇笔记Builder设计模式中,时の魔导士祭出了自己的WorldCreator.尽管它因此能创造出一个有山有树有房子的世界,但是白 ...
- [学习笔记]设计模式之Adapter
写在前面 为方便读者,本文已添加至索引: 设计模式 学习笔记索引 Adapter(适配器)模式主要解决接口不匹配的问题.为此,让我们要回到最初Builder模式创建平行世界时,白雪公主和小霍比特人的谜 ...
- [学习笔记]设计模式之Prototype
写在前面 为方便读者,本文已添加至索引: 设计模式 学习笔记索引 在笔记Builder模式中,我们曾见到了最初用于创建平行世界的函数createWorld,并且它是Mage类的成员函数(毕竟是专属于魔 ...
- [学习笔记]设计模式之Proxy
为方便读者,本文已添加至索引: 设计模式 学习笔记索引 写在前面 “魔镜啊魔镜,谁是这个世界上最美丽的人?” 每到晚上,女王都会问魔镜相同的问题(见Decorator模式).这是她还曾身为女巫时留下的 ...
- [学习笔记]设计模式之Bridge
写在前面 为方便读者,本文已添加至索引: 设计模式 学习笔记索引 “魔镜啊魔镜,谁是这个世界上最美丽的人?”月光中,一个低沉的声音回荡在女王的卧室.“是美丽的白雪公主,她正和小霍比特人们幸福快乐地生活 ...
- [学习笔记]设计模式之Command
为方便读者,本文已添加至索引: 设计模式 学习笔记索引 写在前面 在上篇Chain of Responsibility(职责链)模式笔记中,我们学习了一种行为型设计模式.今天,我们继续这一主题,来学习 ...
- [学习笔记]设计模式之Chain of Responsibility
为方便读者,本文已添加至索引: 设计模式 学习笔记索引 写在前面 最近时间比较紧,所以发文的速度相对较慢了.但是看到园子里有很多朋友对设计模式感兴趣,我感觉很高兴,能够和大家一起学习这些知识. 之前的 ...
- [学习笔记]设计模式之Composite
为方便读者,本文已添加至索引: 设计模式 学习笔记索引 写在前面 在Composite(组合)模式中,用户可以使用多个简单的组件以形成较大的组件,而这些组件还可能进一步组合成更大的.它重要的特性是能够 ...
- [学习笔记]设计模式之Flyweight
为方便读者,本文已添加至索引: 设计模式 学习笔记索引 写在前面 Flyweight(享元)模式运用共享技术,可以有效地支持大量细粒度的对象.今天我们会去参观小霍比特人们的酿酒工坊……等等,不是享元模 ...
随机推荐
- svn-主副分支使用
主改bug 副加功能, :主合并到副(在副中切换主分支),副调试成功,合并回主(在主切换回副分支) 奇葩的实现了需求 主改bug 副加功能, :主合并到副(在副中切换主分支),副调试成功,合并回主(在 ...
- c#自动更新+安装程序的制作 (转)
c#自动更新+安装程序的制作 (转) http://blog.csdn.net/myhuli120/article/details/6927588 一.自动更新的实现 让客户端实现自动更新,通常做法 ...
- vs2013 IHttpActionResult NotFund Ok (WebAPI)
vs2013 IHttpActionResult NotFund Ok 使用ASP.NET Web API构造基于restful风格web services,IHttpActionResult是 ...
- NDK_ROOT找不到的解决方法 MACOS
只要在Eclipse上进行配置就行了,看图说话
- chmod 命令 set uid ,set gid,sticky bit 说明
permission的符号模式表: 模式 名字 说明 r 读 设置为可读权限 w 写 设置为可写权限 x 执行权限 设置为可执行权限 X 特殊执行权限 只有当文件为目录文件,或者其他类型的用户有可执行 ...
- iOS- static extern const
1.静态变量 static 什么是静态变量:从面向对象的角度触发,当需要一个数据对象为整类而非某个对象服务,同时有力求不破坏类的封装性,既要求此成员隐藏在类的内部,有要求对外不可见的时候,就可以使用 ...
- 使用SeaJS实现模块化JavaScript开发(新)
本文转自张洋,因为SeaJS更新版本很快,所以原文中很多地方不太适用,在这里发布一个更新版. 前言 SeaJS是一个遵循CommonJS规范的JavaScript模块加载框架,可以实现JavaSc ...
- 网络流系列算法总结(bzoj 3438 1061)
网络流嘛,怎么看都是一堆逗逼题嘛,反正遇到还是都做不起嘛.... 网络流的模板非常简单,难点都在于建图,网络流的建图解决问题范围之广,下至A+B Problem,上至单纯形,线性规划.所以如果对于网络 ...
- OSAL多任务资源分配机制
转自OSAL多任务资源分配机制 一.概述 OSAL (Operating System Abstraction Layer),翻译为"操作系统抽象层". 个应用程序对象. ...
- Java 声明和访问控制(三) finalize方法 成员访问修饰符
finalize()方法是Object类的一个方法,在垃圾回收器执行的时候,会调用被回收对象的此方法,可以覆盖此方法提供垃圾收集时的其他资源的回收,例如文件关闭等. 成员访问修饰符: 默认访问:包访问 ...