概述

在软件系统中,有时候面临着“一个复杂对象”的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法确相对稳定。如何应对这种变化?如何提供一种“封装机制”来隔离出“复杂对象的各个部分”的变化,从而保持系统中的“稳定构建算法”不随着需求改变而改变?这就是要说的建造者模式。

本文通过现实生活中的买KFC的例子,用图解的方式来诠释建造者模式。

意图

将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。

模型图

生活中的例子

生成器模式将复杂对象的构建与对象的表现分离开来,这样使得同样的构建过程可以创建出不同的表现。这种模式用于快餐店制作儿童餐。典型的儿童餐包括一个主食,一个辅食,一杯饮料和一个玩具(例如汉堡、炸鸡、可乐和玩具车)。这些在不同的儿童餐中可以是不同的,但是组合成儿童餐的过程是相同的。无论顾客点的是汉堡,三名治还是鸡肉,过程都是一样的。柜台的员工直接把主食,辅食和玩具放在一起。这些是放在一个袋子中的。饮料被倒入杯中,放在袋子外边。这些过程在相互竞争的餐馆中是同样的。

实现过程图解

在这里我们还是以去KFC店买套餐为例子,示意图如下:

客户端:顾客。想去买一套套餐(这里面包括汉堡,可乐,薯条),可以有1号和2号两种套餐供顾客选择。

指导者角色:收银员。知道顾客想要买什么样的套餐,并告诉餐馆员工去准备套餐。

建造者角色:餐馆员工。按照收银员的要求去准备具体的套餐,分别放入汉堡,可乐,薯条等。

产品角色:最后的套餐,所有的东西放在同一个盘子里面。

下面开始我们的买套餐过程。

1.客户创建Derector对象,并用它所想要的Builder对象进行配置。顾客进入KFC店要买套餐,先找到一个收银员,相当于创建了一个指导者对象。这位收银员给出两种套餐供顾客选择:1普通套餐,2黄金套餐。完成的工作如时序图中红色部分所示。

程序实现:

产品(套餐)类:

2.指导者通知建造器。收银员(指导者)告知餐馆员工准备套餐。这里我们准备套餐的顺序是:放入汉堡,可乐倒入杯中,薯条放入盒中,并把这些东西都放在盘子上。这个过程对于普通套餐和黄金套餐来说都是一样的,不同的是它们的汉堡,可乐,薯条价格不同而已。如时序图红色部分所示:

程序实现:

3.建造者处理指导者的要求,并将部件添加到产品中。餐馆员工(建造者)按照收银员要求的把对应的汉堡,可乐,薯条放入盘子中。这部分是建造者模式里面富于变化的部分,因为顾客选择的套餐不同,套餐的组装过程也不同,这步完成产品对象的创建工作。

程序实现:

4.客户从建造者检索产品。从餐馆员工准备好套餐后,顾客再从餐馆员工那儿拿回套餐。这步客户程序要做的仅仅是取回已经生成的产品对象,如时序图中红色部分所示。

完整的客户程序:

通过分析不难看出,在这个例子中,在准备套餐的过程是稳定的,即按照一定的步骤去做,而套餐的组成部分则是变化的,有可能是普通套餐或黄金套餐等。这个变化就是建造者模式中的“变化点“,就是我们要封装的部分。

另外一个例子

在这里我们再给出另外一个关于建造房子的例子。客户程序通过调用指导者 (CDirector class)的BuildHouse()方法来创建一个房子。该方法有一个布尔型的参数blnBackyard,当blnBackyard为假时指导者将创建一个Apartment(Concrete Builder),当它为真时将创建一个Single Family Home(Concrete Builder)。这两种房子都实现了接口Ihouse。

程序实现:

建造者模式的几种演化

省略抽象建造者角色

系统中只需要一个具体建造者,省略掉抽象建造者,结构图如下:

指导者代码如下:

 }

省略指导者角色

抽象建造者角色已经被省略掉,还可以省略掉指导者角色。让Builder角色自己扮演指导者与建造者双重角色。结构图如下:

建造者角色代码如下:

 }

客户程序:

 }

合并建造者角色和产品角色

建造模式失去抽象建造者角色和指导者角色后,可以进一步退化,从而失去具体建造者角色,此时具体建造者角色和产品角色合并,从而使得产品自己就是自己的建造者。这样做混淆了对象的建造者和对象本身,但是有时候一个产品对象有着固定的几个零件,而且永远只有这几个零件,此时将产品类和建造类合并,可以使系统简单易读。结构图如下:

实现要点

1、建造者模式主要用于“分步骤构建一个复杂的对象”,在这其中“分步骤”是一个稳定的算法,而复杂对象的各个部分则经常变化。

2、产品不需要抽象类,特别是由于创建对象的算法复杂而导致使用此模式的情况下或者此模式应用于产品的生成过程,其最终结果可能差异很大,不大可能提炼出一个抽象产品类。
3、创建者中的创建子部件的接口方法不是抽象方法而是空方法,不进行任何操作,具体的创建者只需要覆盖需要的方法就可以,但是这也不是绝对的,特别是类似文本转换这种情况下,缺省的方法将输入原封不动的输出是合理的缺省操作。

4、前面我们说过的抽象工厂模式(Abtract Factory)解决“系列对象”的需求变化,Builder模式解决“对象部分”的需求变化,建造者模式常和组合模式(Composite Pattern)结合使用。

效果

1、建造者模式的使用使得产品的内部表象可以独立的变化。使用建造者模式可以使客户端不必知道产品内部组成的细节。
2、每一个Builder都相对独立,而与其它的Builder无关。
3、可使对构造过程更加精细控制。

4、将构建代码和表示代码分开。

5、建造者模式的缺点在于难于应付“分步骤构建算法”的需求变动。

适用性

以下情况应当使用建造者模式:

1、需要生成的产品对象有复杂的内部结构。
2、需要生成的产品对象的属性相互依赖,建造者模式可以强迫生成顺序。
3、 在对象创建过程中会使用到系统中的一些其它对象,这些对象在产品对象的创建过程中不易得到。

应用场景

1、   RTF文档交换格式阅读器。

2、   .NET环境下的字符串处理StringBuilder,这是一种简化了的建造者模式。

3、   ……

总结

建造者模式的实质是解耦组装过程和创建具体部件,使得我们不用去关心每个部件是如何组装的。

______________________________________________________________________________________

源程序下载:/Files/Terrylee/BuilderPattern.rar

参考资料:

《Java与设计模式》阎宏著

《设计模式(中文版)》

《DesignPatternsExplained》

.NET设计模式(4):建造者模式(Builder Pattern)(转)的更多相关文章

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

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

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

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

  3. 二十四种设计模式:建造者模式(Builder Pattern)

    建造者模式(Builder Pattern) 介绍将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. 示例用同样的构建过程创建Sql和Xml的Insert()方法和Get()方 ...

  4. Python 设计模式之建造者模式 Builder Pattern

    #引入建造者模式 肯德基的菜单上有 薯条, 鸡腿,鸡翅,鸡米花,可乐,橙汁,火腿汉堡,至尊虾汉堡,牛肉汉堡 , 鸡肉卷等这些单品,也有很多套餐. 比如 套餐1:鸡翅,至尊虾汉堡,可乐,薯条 套餐2:鸡 ...

  5. 设计模式-05建造者模式(Builder Pattern)

    1.模式动机 比如我们要组装一台电脑,都知道电脑是由 CPU.主板.内存.硬盘.显卡.机箱.显示器.键盘和鼠标组成,其中非常重要的一点就是这些硬件都是可以灵活选择,但是组装步骤都是大同小异(可以组一个 ...

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

    概述 描述 建造者模式,又称生成器模式.是将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. 建造者模式将客户端与包含多个组成部分的复杂对象的创建过程分离,客户端无需知道复杂 ...

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

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

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

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

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

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

  10. 建造者模式(Builder Pattern)

    建造者模式(Builder Pattern) 它可以将多个简单的对象一步一步构建成一个复杂的对象. 意图:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示. 主要解决:主要解决在软 ...

随机推荐

  1. IBM开发者 JSON 教程

    在异步应用程序中发送和接收信息时,可以选择以纯文本和 XML 作为数据格式.掌握 Ajax 的这一期讨论另一种有用的数据格式 JavaScript Object Notation(JSON),以及如何 ...

  2. vim之旅

    本人是今年的毕业生, 大学很莫名的选择了一个电子商务专业. 由于专业没有实质性的东西可学,加上对电商不敢兴趣, 于是乎我有了大量的时间在宿舍里折腾电脑. 折腾了几年大三决定转业, 大四在还没找工作之前 ...

  3. Python核心编程--学习笔记--8--条件与循环

    本章讲述if.while.for以及与他们搭配的else.elif.break.continue.pass等语句. 1 if语句 语法:三部分——关键字if.条件表达式.代码块.(记住冒号) if c ...

  4. QPBOC扩展应用交易流程

    1 Q扩展部分数据 增加3个DGI,分别为:A001,8020,9020 9103中增加DF60(9F38中),DF61 增加DF62,DF63 1.1  A001扩展应用配置 DGI 长度 值(示例 ...

  5. C# WinForm自定义控件响应键盘事件

    自己定义的winform控件,用其他键盘事件都无法响应,只有用ProcessCmdKey事件可以达到目的(别忘了主窗体的KeyPreview属性要设置为true),写法如下:         prot ...

  6. node.js 在 Express4.0 框架使用 Connect-Busboy 实现文件上传

    node.js下四种post提交数据的方式 今天说分享的是其中一种,就是上传文件. Express 4.0 以后,将功能原子化,高内聚,低耦合,独立出了很多中间件 今天主要分享文件上传 对于conne ...

  7. hdu 5224 Tom and paper

    题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5224 Tom and paper Description There is a piece of pa ...

  8. wpa_supplicant测试

    Android系统中对于WIFI的设置集成到了“设置”中,其实跟手动设置差不多.这里介绍下如何手动连接WIFI,以方便以后调试WIFI. 第一步要做的就是要加载WIFI模块驱动了.当然如果你的WIFI ...

  9. mysql存储过程执行权限问题

    tags: mysql  PROCEDURE 存储过程 definer SECURITY 权限 以下存储过程,限定了DEFINER为root,也就是root之外的账户是无法调用这个存储过程的. 1 2 ...

  10. iOS学习之视图控制器

    一.自定义视图(label-textField组合视图)      1.自定义视图:系统标准UI之外,自己组合出的新的视图.      2.优点:iOS提供了很多UI组件,借助它们我们可以实现不同的功 ...