设计模式之建造者模式Builder(创建型)
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
 - /**
 - * 指导者:收银员
 - *
 - */
 - class DirectorCashier
 - {
 - /**
 - * 收银餐馆员工返回的食物
 - *
 - */
 - public function buildFood(Builder $builder) {
 - $builder->buildPart1();
 - $builder->buildPart2();
 - }
 - }
 
抽象建造者:
- /**
 - * 抽象建造者
 - *
 - */
 - abstract class Builder
 - {
 - /**
 - * 创建产品的第一部分
 - */
 - public abstract function buildPart1();
 - /**
 - *
 - * 创建产品的第二部分
 - */
 - public abstract function buildPart2();
 - /**
 - *
 - * 返回产品
 - */
 - public abstract function getProduct();
 - }
 
具体建造者类:
- /**
 - * 具体建造者类:餐馆员工,返回的套餐是:汉堡两个+饮料一个
 - *
 - */
 - class ConcreteBuilder1 extends Builder
 - {
 - protected $_product = null;//产品对象
 - function __construct(){
 - $this->_product = new Product();
 - }
 - /**
 - * 创建产品的第一部分::汉堡=2
 - */
 - public function buildPart1()
 - {
 - $this->_product->add('Hamburger',2);
 - }
 - /**
 - *
 - * 创建产品的第二部分:
 - */
 - public function buildPart2()
 - {
 - $this->_product->add('Drink', 1);
 - }
 - /**
 - * 返回产品对象 :
 - *
 - */
 - public function getProduct() {
 - return $this->_product;
 - }
 - }
 - /**
 - * 具体建造者类:餐馆员工,汉堡1个+饮料2个
 - *
 - */
 - class ConcreteBuilder2 extends Builder
 - {
 - protected $_product = null;//产品对象
 - function __construct(){
 - $this->_product = new Product();
 - }
 - /**
 - * 创建产品的第一部分:汉堡
 - */
 - public function buildPart1()
 - {
 - $this->_product->add('Hamburger', 1);
 - }
 - /**
 - *
 - * 创建产品的第二部分:drink=2
 - */
 - public function buildPart2()
 - {
 - $this->_product->add('Drink', 2);
 - }
 - /**
 - * 返回产品对象 :
 - *
 - */
 - public function getProduct() {
 - return $this->_product;
 - }
 - }
 
产品类:
- /**
 - * 产品类
 - */
 - class Product
 - {
 - public $products = array();
 - /**
 - * 添加具体产品
 - */
 - public function add($name, $value) {
 - $this->products[$name] = $value;
 - }
 - /**
 - * 给顾客查看产品
 - */
 - public function showToClient()
 - {
 - foreach ($this->products as $key => $v) {
 - echo $key , '=' , $v ,'<br>';
 - }
 - }
 - }
 
- 客户程序:
 
- <pre name="code" class="php"> //客户程序
 - class Client
 - {
 - /**
 - * 顾客购买套餐
 - *
 - */
 - public function buy($type) {
 - //指导者,收银员
 - $director = new DirectorCashier();
 - //餐馆员工,收银员
 - $class = new ReflectionClass('ConcreteBuilder' .$type );
 - $concreteBuilder = $class->newInstanceArgs();
 - //收银员组合员工返回的食物
 - $director->buildFood($concreteBuilder);
 - //返回给顾客
 - $concreteBuilder->getProduct()->showToClient();
 - }
 - }
 - //测试
 - ini_set('display_errors', 'On');
 - $c = new Client();
 - $c->buy(1);//购买套餐1
 - $c->buy(2);//购买套餐1</pre>
 - <pre></pre>
 - <pre></pre>
 - <pre></pre>
 
9. 建造者模式的优点
首先,建造者模式的封装性很好。使用建造者模式可以有效的封装变化,在使用建造者模式的场景中,一般产品类和建造者类是比较稳定的,因此,将主要的业务逻辑封装在导演类中对整体而言可以取得比较好的稳定性。
其次,建造者模式很容易进行扩展。如果有新的需求,通过实现一个新的建造者类就可以完成,基本上不用修改之前已经测试通过的代码,因此也就不会对原有功能引入风险。
10. 建造者模式与工厂模式的区别
我们可以看到,建造者模式与工厂模式是极为相似的,总体上,建造者模式仅仅只比工厂模式多了一个“导演类”的角色。在建造者模式的类图中,假如把这个导演类看做是最终调用的客户端,那么图中剩余的部分就可以看作是一个简单的工厂模式了。
与工厂模式相比,建造者模式一般用来创建更为复杂的对象,因为对象的创建过程更为复杂,因此将对象的创建过程独立出来组成一个新的类——导演类。也就是说,工厂模式是将对象的全部创建过程封装在工厂类中,由工厂类向客户端提供最终的产品;而建造者模式中,建造者类一般只提供产品类中各个组件的建造,而将具体建造过程交付给导演类。由导演类负责将各个组件按照特定的规则组建为产品,然后将组建好的产品交付给客户端。
11. 总结
建造者模式与工厂模式类似,他们都是建造者模式,适用的场景也很相似。一般来说,如果产品的建造很复杂,那么请用工厂模式;如果产品的建造更复杂,那么请用建造者模式。
原文链接:http://blog.csdn.net/hguisu/article/details/7518060
设计模式之建造者模式Builder(创建型)的更多相关文章
- Java设计模式04:常用设计模式之建造者模式(创建型模式)
		
1. Java之建造者模式(Builder Pattern) (1)概念: 将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示. [ 构建与表示分离, 同构建不同表示 ] ...
 - 乐在其中设计模式(C#) - 建造者模式(Builder Pattern)
		
原文:乐在其中设计模式(C#) - 建造者模式(Builder Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 建造者模式(Builder Pattern) 作者:webabc ...
 - 【设计模式】建造者模式 Builder Pattern
		
前面学习了简单工厂模式,工厂方法模式以及抽象工厂模式,这些都是创建类的对象所使用的一些常用的方法和套路, 那么如果我们创建一个很复杂的对象可上面的三种方法都不太适合,那么“专业的事交给专业人去做”,2 ...
 - 设计模式-05建造者模式(Builder Pattern)
		
1.模式动机 比如我们要组装一台电脑,都知道电脑是由 CPU.主板.内存.硬盘.显卡.机箱.显示器.键盘和鼠标组成,其中非常重要的一点就是这些硬件都是可以灵活选择,但是组装步骤都是大同小异(可以组一个 ...
 - 二十四种设计模式:建造者模式(Builder Pattern)
		
建造者模式(Builder Pattern) 介绍将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. 示例用同样的构建过程创建Sql和Xml的Insert()方法和Get()方 ...
 - Python 设计模式之建造者模式   Builder Pattern
		
#引入建造者模式 肯德基的菜单上有 薯条, 鸡腿,鸡翅,鸡米花,可乐,橙汁,火腿汉堡,至尊虾汉堡,牛肉汉堡 , 鸡肉卷等这些单品,也有很多套餐. 比如 套餐1:鸡翅,至尊虾汉堡,可乐,薯条 套餐2:鸡 ...
 - 【UE4 设计模式】建造者模式 Builder Pattern
		
概述 描述 建造者模式,又称生成器模式.是将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. 建造者模式将客户端与包含多个组成部分的复杂对象的创建过程分离,客户端无需知道复杂 ...
 - 创建型设计模式之建造者模式(Builder)
		
结构 意图 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示. 适用性 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时. 当构造过程必须允许被构造的对象有不 ...
 - Java设计模式——建造者模式(创建型模式)
		
概述 建造者模式也称为生成器模式,是一种对象创建型模式,它可以将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象. 建造者模式意在为重叠构造 ...
 
随机推荐
- Linux内核的基本概念
			
Linux内核学习,推荐的书籍: <linux设备驱动开发详解第二版>.<Linux内核设计与实现第三版>.<嵌入式Linux应用开发完全手册> 第一篇:讲解Lin ...
 - (转载)Oracle10g 数据泵导出命令 expdp 使用总结(一)
			
原文链接:http://hi.baidu.com/edeed/item/890626ef6f6d9d265b2d646f Oracle10g 数据泵导出命令 expdp 使用总结(二)Oracle10 ...
 - (转载)java基础:关于java流与文件操作
			
原文摘自: http://www.blogjava.net/haizhige/archive/2008/08/03/219668.html 1.描述:流是字节数据或字符数据序列. Java采用输入流对 ...
 - 我的学习之路_第二十九章_bootstrap
			
bootstrap 内置了html,css,js插件为一体的前端框架 响应式布局: 设计一套页面就可以使用于很多现实设备 bootstrap: 1.入门(响应式布局的容器) 1.先进入jQuery的j ...
 - Java 9 揭秘(10. 模块API)
			
Tips 做一个终身学习的人. 在本章节中,主要介绍以下内容: 什么是模块 API 如何在程序中表示模块和模块描述 如何读取程序中的模块描述 如何表示模块的版本 如何使用Module和ModuleDe ...
 - Spring Security  @PreAuthorize 拦截无效
			
1. 在使用spring security的时候使用注解,@PreAuthorize("hasAnyRole('ROLE_Admin')") 放在对方法的访问权限进行控制失效,其中 ...
 - 虚拟机配置静态IP地址
			
使用VMware配置虚拟机静态IP地址 一.安装好虚拟后在菜单栏选择编辑→ 虚拟网络编辑器,打开虚拟网络编辑器对话框,选择Vmnet8 Net网络连接方式,随意设置子网IP,点击NAT设置页面,查看子 ...
 - python新手之2变量
			
变量 变量是将储存的值保存在内存中.当声明一个变量的时候会在内存中开辟一个储存内容的位置. 基于变量的数据类型,解释器分配内存空间并决定储存的内容.因此我们可以通过变量分配不同的数据类型,可以在变量中 ...
 - java开发必读 书单
			
希望读的书单 重构 改善既有代码的设计 设计模式 可复用面向对象软件的基础 高性能MySQL第3版 Effective Java第1版 Effective Java第2版 Java核心技术I-基础知识 ...
 - HDU 3829 Cat VS Dog / NBUT 1305 Cat VS Dog(二分图最大匹配)
			
HDU 3829 Cat VS Dog / NBUT 1305 Cat VS Dog(二分图最大匹配) Description The zoo have N cats and M dogs, toda ...