【转】设计模式(三)建造者模式Builder(创建型)

http://blog.csdn.net/hguisu/article/details/7518060

1. 概述

在软件开发的过程中,当遇到一个“复杂的对象”的创建工作,该对象由一定各个部分的子对象用一定的算法构成,由于需求的变化,复杂对象的各个部分经常面临剧烈的变化,但将它们组合在一起的算法相对稳定。

例子1:买肯德基

典型的儿童餐包括一个主食,一个辅食,一杯饮料和一个玩具(例如汉堡、炸鸡、可乐和玩具车)。这些在不同的儿童餐中可以是不同的,但是组合成儿童餐的过程是相同的。


       客户端:顾客,想去买一套套餐(这里面包括汉堡,可乐,薯条),可以有1号和2号两种套餐供顾客选择。
       指导者角色:收银员。知道顾客想要买什么样的套餐,并告诉餐馆员工去准备套餐。
       建造者角色:餐馆员工。按照收银员的要求去准备具体的套餐,分别放入汉堡,可乐,薯条等。
       产品角色:最后的套餐,所有的东西放在同一个盘子里面。

例子2:计算工资:工资的计算一般是:底薪+奖金-税。但底薪分为一级8000、二级6000、三级4000三个等级。根据岗位不同奖金的发放也不一样,管理及日常事务处理岗位(A类)每月根据领导及同事间的评议得分计算奖金,销售岗位(B类)则根据销售额发放提成。税金则根据奖金和底薪的数额进行计算。由此看出该工资的计算方式是比较稳定的构建算法,但对工资的每一部分都会根据不同的情况产生不同的算法,如何将客户端与变化巨烈的底薪、奖金和税金计算方式分离呢,这也比较适合用建造者模式。

2 . 问题

我们如何应对这种变化,如何提供一种“封装机制”来隔离“复杂对象的各个部”的变化,从而保持系统中的“稳定构建算法”而不随需求的变化而变化?

3. 解决方案

建造者模式: 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

4. 适用性

在以下情况使用Builder模式

?当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。

?当构造过程必须允许被构造的对象有不同的表示时。

5. 结 构

此模式结构如下页上图所示。

6. 构建模式的组成

? 抽象建造者角色(Builder):为创建一个Product对象的各个部件指定抽象接口,以规范产品对象的各个组成成分的建造。一般而言,此角色规定要实现复杂对象的哪些部分的创建,并不涉及具体的对象部件的创建。
具体建造者(ConcreteBuilder)

1)实现Builder的接口以构造和装配该产品的各个部件。即实现抽象建造者角色Builder的方法。

2)定义并明确它所创建的表示,即针对不同的商业逻辑,具体化复杂对象的各部分的创建

3)  提供一个检索产品的接口

4)   构造一个使用Builder接口的对象即在指导者的调用下创建产品实例

指导者(Director):调用具体建造者角色以创建产品对象的各个部分。指导者并没有涉及具体产品类的信息,真正拥有具体产品的信息是具体建造者对象。它只负责保证对象各部分完整创建或按某种顺序创建。

产品角色(Product):建造中的复杂对象。它要包含那些定义组件的类,包括将这些组件装配成产品的接口。

7. 效果

Builder模式的主要效果:

1 ) 它使你可以改变一个产品的内部表示 Builder对象提供给导向器一个构造产品的抽象接口。该接口使得生成器可以隐藏这个产品的表示和内部结构。它同时也隐藏了该产品是如何装配的。因为产品是通过抽象接口构造的,你在改变该产品的内部表示时所要做的只是定义一个新的生成器。

2) 它将构造代码和表示代码分开 Builder模式通过封装一个复杂对象的创建和表示方式提高了对象的模块性。客户不需要知道定义产品内部结构的类的所有信息;这些类是不出现在Builder接口中的。每个Concrete Builder包含了创建和装配一个特定产品的所有代码。这些代码只需要写一次;然后不同的Director可以复用它以在相同部件集合的基础上构作不同的Product。

3 ) 它使你可对构造过程进行更精细的控制 Builder模式与一下子就生成产品的创建型模式不同,它是在导向者的控制下一步一步构造产品的。仅当该产品完成时导向者才从生成器中取回它。因此Builder接口相比其他创建型模式能更好的反映产品的构造过程。这使你可以更精细的控制构建过程,从而能更精细的控制所得产品的内部结构。

8. 实现:

指导者:收银员

[php] view plain copy

print?

  1. <?php
  2. /**
  3. * 指导者:收银员
  4. *
  5. */
  6. class DirectorCashier
  7. {
  8. /**
  9. * 收银餐馆员工返回的食物
  10. *
  11. */
  12. public function buildFood(Builder $builder) {
  13. $builder->buildPart1();
  14. $builder->buildPart2();
  15. }
  16. }

抽象建造者:

[php] view plain copy

print?

  1. /**
  2. * 抽象建造者
  3. *
  4. */
  5. abstract class Builder
  6. {
  7. /**
  8. * 创建产品的第一部分
  9. */
  10. public abstract function buildPart1();
  11. /**
  12. *
  13. * 创建产品的第二部分
  14. */
  15. public abstract function buildPart2();
  16. /**
  17. *
  18. *  返回产品
  19. */
  20. public abstract function getProduct();
  21. }

具体建造者类:

[php] view plain copy

print?

  1. /**
  2. * 具体建造者类:餐馆员工,返回的套餐是:汉堡两个+饮料一个
  3. *
  4. */
  5. class ConcreteBuilder1 extends Builder
  6. {
  7. protected $_product = null;//产品对象
  8. function __construct(){
  9. $this->_product = new Product();
  10. }
  11. /**
  12. * 创建产品的第一部分::汉堡=2
  13. */
  14. public  function buildPart1()
  15. {
  16. $this->_product->add(‘Hamburger‘,2);
  17. }
  18. /**
  19. *
  20. * 创建产品的第二部分:
  21. */
  22. public  function buildPart2()
  23. {
  24. $this->_product->add(‘Drink‘, 1);
  25. }
  26. /**
  27. * 返回产品对象 :
  28. *
  29. */
  30. public function  getProduct()  {
  31. return  $this->_product;
  32. }
  33. }
  34. /**
  35. * 具体建造者类:餐馆员工,汉堡1个+饮料2个
  36. *
  37. */
  38. class ConcreteBuilder2 extends Builder
  39. {
  40. protected $_product = null;//产品对象
  41. function __construct(){
  42. $this->_product = new Product();
  43. }
  44. /**
  45. * 创建产品的第一部分:汉堡
  46. */
  47. public  function buildPart1()
  48. {
  49. $this->_product->add(‘Hamburger‘, 1);
  50. }
  51. /**
  52. *
  53. * 创建产品的第二部分:drink=2
  54. */
  55. public  function buildPart2()
  56. {
  57. $this->_product->add(‘Drink‘, 2);
  58. }
  59. /**
  60. * 返回产品对象 :
  61. *
  62. */
  63. public function  getProduct()  {
  64. return  $this->_product;
  65. }
  66. }

产品类:

[php] view plain copy

print?

  1. /**
  2. * 产品类
  3. */
  4. class Product
  5. {
  6. public $products = array();
  7. /**
  8. * 添加具体产品
  9. */
  10. public function add($name,  $value) {
  11. $this->products[$name] = $value;
  12. }
  13. /**
  14. * 给顾客查看产品
  15. */
  16. public function showToClient()
  17. {
  18. foreach ($this->products as $key => $v) {
  19. echo $key , ‘=‘ , $v ,‘<br>‘;
  20. }
  21. }
  22. }

[php] view plain copy

print?

  1. 客户程序:

[php] view plain copy

print?

  1. <pre name="code" class="php"> //客户程序
  2. class Client
  3. {
  4. /**
  5. * 顾客购买套餐
  6. *
  7. */
  8. public  function buy($type) {
  9. //指导者,收银员
  10. $director  = new DirectorCashier();
  11. //餐馆员工,收银员
  12. $class = new ReflectionClass(‘ConcreteBuilder‘ .$type );
  13. $concreteBuilder  = $class->newInstanceArgs();
  14. //收银员组合员工返回的食物
  15. $director->buildFood($concreteBuilder);
  16. //返回给顾客
  17. $concreteBuilder->getProduct()->showToClient();
  18. }
  19. }
  20. //测试
  21. ini_set(‘display_errors‘, ‘On‘);
  22. $c = new Client();
  23. $c->buy(1);//购买套餐1
  24. $c->buy(2);//购买套餐1</pre>
  25. <pre></pre>
  26. <pre></pre>
  27. <pre></pre>

9. 建造者模式的优点

首先,建造者模式的封装性很好。使用建造者模式可以有效的封装变化,在使用建造者模式的场景中,一般产品类和建造者类是比较稳定的,因此,将主要的业务逻辑封装在导演类中对整体而言可以取得比较好的稳定性。

其次,建造者模式很容易进行扩展。如果有新的需求,通过实现一个新的建造者类就可以完成,基本上不用修改之前已经测试通过的代码,因此也就不会对原有功能引入风险。

10. 建造者模式与工厂模式的区别

我们可以看到,建造者模式与工厂模式是极为相似的,总体上,建造者模式仅仅只比工厂模式多了一个“导演类”的角色。在建造者模式的类图中,假如把这个导演类看做是最终调用的客户端,那么图中剩余的部分就可以看作是一个简单的工厂模式了。

与工厂模式相比,建造者模式一般用来创建更为复杂的对象,因为对象的创建过程更为复杂,因此将对象的创建过程独立出来组成一个新的类——导演类。也就是说,工厂模式是将对象的全部创建过程封装在工厂类中,由工厂类向客户端提供最终的产品;而建造者模式中,建造者类一般只提供产品类中各个组件的建造,而将具体建造过程交付给导演类。由导演类负责将各个组件按照特定的规则组建为产品,然后将组建好的产品交付给客户端。

11. 总结

建造者模式与工厂模式类似,他们都是建造者模式,适用的场景也很相似。一般来说,如果产品的建造很复杂,那么请用工厂模式;如果产品的建造更复杂,那么请用建造者模式。

时间: 2024-10-12 17:49:09

【转】设计模式(三)建造者模式Builder(创建型)的相关文章

设计模式-04 建造者模式(创建型模式)

一 建造者模式 建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 主要解决:在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成:由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定. 关键代码 : 建造者:创建和提供实例,导演:管理建造出来的实例的依赖关系. 使用场景: 汽车有很多部件,车轮

设计模式之建造者模式Builder(创建型)

1. 概述 在软件开发的过程中,当遇到一个“复杂的对象”的创建工作,该对象由一定各个部分的子对象用一定的算法构成,由于需求的变化,复杂对象的各个部分经常面临剧烈的变化,但将它们组合在一起的算法相对稳定. 例子1:买肯德基 典型的儿童餐包括一个主食,一个辅食,一杯饮料和一个玩具(例如汉堡.炸鸡.可乐和玩具车).这些在不同的儿童餐中可以是不同的,但是组合成儿童餐的过程是相同的.        客户端:顾客,想去买一套套餐(这里面包括汉堡,可乐,薯条),可以有1号和2号两种套餐供顾客选择.      

设计模式(三)建造者模式(创建型)

定义:将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. 使用场景: 创建的产品有复杂的内部结构,且创建的产品有较多的共同点,其组成部分相似.隔离复杂对象的创建,使得相同的过程可以创建不同的产品. 与抽象工厂的区别: 在建造者模式里,有个指导者,由指导者来管理创造者,用户是与指导者联系的,指导者联系创建者得到最后的产品. 角色: Builder:一个抽象接口,用于规范定义复杂对象的组成部分. ConcreteBuilder:实现Builder接口,具体化复杂对象的各个部

设计模式--建造者模式(创建型)

一.首先看建造者模式的UML图: 二.再来看一个建造者模式的例子 class Builder { public: virtual void BuildHead() {} virtual void BuildBody() {} virtual void BuildLeftArm(){} virtual void BuildRightArm() {} virtual void BuildLeftLeg() {} virtual void BuildRightLeg() {} }; //构造瘦人 cl

设计模式之建造者模式——Builder

一.概述 Builder模式,中文名为建造者模式,又名生成器模式.构建者模式等,是创建型设计模式之一.用于将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. 1.适用性: 对象的创建比较复杂.有多种创建形式时 创建复杂对象的算法与对象内部组成和装配是相对独立的 2.UML类图 Builder:定义创建Product各个部件的抽象接口 ConcreteBuilder:继承自Builder,实现创建具体类型的Product所有部件的接口,并提供一个获取最终产品的接口. Dir

设计模式-05 原型模式(创建型模式)

一 原型模式 原型模式是用于创建重复的对象,同时又能保证性能. 原型模式用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象. 主要解决: 利用已有的一个原型对象,快速地生成和原型对象一样的实例 关键代码 : 实现克隆操作,在 JAVA 继承 Cloneable,重写 clone() 使用场景: 类初始化需要消化非常多的资源,这个资源包括数据.硬件资源等. 类图: 原型模式主要用于对象的复制,它的核心是就是类图中的原型类Prototype.Prototype类需要具备以下两个条件: 实现

php设计模式三-----建造者模式

1.简介 意图:将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示. 主要解决:主要解决在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成:由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定. 何时使用:一些基本部件不会变,而其组合经常变化的时候. 优点: 1.建造者独立,易扩展. 2.便于控制细节风险. 缺点: 1.产品必须有共同点,范围有限制. 2.如内部变化复杂,会有很多的

设计模式之建造者模式 Builder

本质与使用场景 public interface AirShipBuilder { Engine builderEngine(); OrbitalModule builderOrbitalModule(); EscapeTower builderEscapeTower(); } public class SxtAirShipBuilder implements AirShipBuilder{ //StringBuilder,以后学习XML解析中,JDOM库中的类:DomBuilder,SaxBu

C#设计模式之四建造者模式(Builder Pattern)【创建型】

原文:C#设计模式之四建造者模式(Builder Pattern)[创建型] 一.引言 今天我们要讲讲Builder模式,也就是建造者模式,当然也有叫生成器模式的,英文名称是Builder Pattern.在现实生活中,我们经常会遇到一些构成比较复杂的物品,比如:电脑,它就是一个复杂的物品,它主要是由CPU.主板.硬盘.显卡.机箱等组装而成的.手机当然也是复杂物品,由主板,各种芯片,RAM 和ROM  摄像头之类的东西组成.但是无论是电脑还是手机,他们的组装过程是固定的,就拿手机来说,组装流水线

设计模式(创建型)之建造者模式(Builder Pattern)

PS一句:最终还是选择CSDN来整理发表这几年的知识点,该文章平行迁移到CSDN.因为CSDN也支持MarkDown语法了,牛逼啊! 概述 建造者模式将客户端与包含多个组成部分的复杂对象的创建过程分离,客户端压根不用知道复杂对象的内部组成部分与装配方式,只需要知道所需建造者的类型即可.它关注如何一步一步创建一个的复杂对象,不同的具体建造者定义了不同的创建过程,且具体建造者相互独立,增加新的建造者非常方便,无须修改已有代码,系统具有较好的扩展性. 问题来了... 你可能会有疑惑,建造者模式和抽象工