代码改变世界

大家一起学面向对象设计模式系列Chapter 04 建造者(Builder)

2009-03-18 14:44  GUO Xingwang  阅读(1909)  评论(1编辑  收藏  举报

     这一篇我将向大家讲解建造者(Builder)模式。在上一篇文章中我们主要学习了抽象工厂(Abstract Factory)模式,抽象工厂模式主要解决对不同等级结构的产品的创建工作,主要关注的是创建哪一批产品的问题,而本文所讲的建造者模式主要是解决对于一个产品如何分部创建的问题,这是对于建造者模式的最初描述。同样,这篇文章主要分为两大部分来讲解,第一部分我会对建造者模式的原型进行详细的说明,第二部分会对建造者模式如何解决具体问题进行探讨。

     建造者模式的原型

     描述:

     在软件系统中,有时候面临一个"复杂对象"的创建工作,其通常由各个部分的子对象用一定算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合到一起的算法却相对稳定。

     建造者模式是对对象的创建模式。建造者模式可以将一个产品的内部表象与产品的生成过程分隔开来,从而可以使一个建造过程生成具有不同的内部表象的产品对象。建造者模式利用一个导演者对象和具体建造者对象一个一个地建造出所有的零件,从而建造出完整的产品对象。建造者模式将产品的结构和产品的零件建造过程对客户端隐藏起来,把对建造过程进行指挥的责任和具体建造零件的责任分隔开来,达到责任划分和封装的目的。

      意图:

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

      模式原型UML:

 

     建造者模式涉及到以下角色:

     1、抽象建造者(Builder)角色:给出一个抽象接口,以规范产品对象的各个组成成分的建造。此接口中一般至少规定两个方法,一个是创建部分的方法,例如BuilderPart,另一个是返回结果的方法,例如GetProduct,以约束具体建造者实现。
     2、具体建造者(ConcreteBuilder)角色:担任这个角色的是与应用程序紧密相关的一些类,它们在应用程序的调用下创建产品的实例。这个角色产品实现了抽象建造者接口,主要完成分部创建产品并提供产品对象的实例。
     3、导演者(Director)角色:顾名思义,就是具体指挥使用哪个具体创造者来完成产品的创建,是创建工作的调用者。但是,导演者角色并没有产品类的具体知识,真正拥有产品类的具体知识的是具体建造者角色。
     4、产品(Product)角色:产品角色就是建造中的复杂对象。一般只有对于复杂对象的创建才使用建造者模式,一个系统中会出现多于一个的产品类,而这些产品类并不一定有共同的接口,可能完全不关联,这时就需要提供多套抽象和具体的建造者来完成不一致的产品的创建或者是采用一个统一接口来标识产品,我个人推荐前者。请大家注意,这里的产品只是一个产品类,不存在继承关系,所以也就没有像抽象工厂中的那种客户端依赖抽象的说法了。

     模式原型代码:

Builder pattern code in C#

输出结果为:

Product Parts -------
PartA
PartB

Product Parts -------
PartX
PartY

     生活中的实例:

     这个小例子向大家展示了一辆车是如何利用建造者模式被创建的,注意商店(这里就是导演者)是如何利用VehicleBuilders按照一定的顺序创建一辆车的。

Real world code using Abstract Factory in C#

输出结果为:

---------------------------
Vehicle Type: Scooter
Frame  : Scooter Frame
Engine : none
#Wheels: 2
#Doors : 0

---------------------------
Vehicle Type: Car
Frame  : Car Frame
Engine : 2500 cc
#Wheels: 4
#Doors : 4

---------------------------
Vehicle Type: MotorCycle
Frame  : MotorCycle Frame
Engine : 500 cc
#Wheels: 2
#Doors : 0

     什么情况下使用建造者:

1、需要生成的产品对象有复杂的内部结构。每一个内部成分本身可以是对象,也可以仅仅是一个对象的组成部分。
2、需要生成的产品对象的属性相互依赖。建造者模式可以强制实行一种分步骤进行的建造过程,因此,如果对象的一个属性必须在另一个属性被赋值之后才可以被赋值,使用建造者模式便是一个很好的设计思想。
3、在对象创建过程中会使用到系统中的其他一些对象,这些对象在产品对象的创建过程中不易得到。

     实际项目举例

     现在我们需要在一个在PC游戏中构建房子的程序。可以构建的房子有多种样式,但是房屋的结构是相对稳定的,每个房子都有地基,墙面,房间,门,窗,地板等,同时也存在一定的构建顺序(必须先构建地基,这也就是产品类的组成部分之间的依赖关系),房子的具体风格可能包括很多种,例如居民住房,存放货物的仓储房等。由于房子的结构稳定,变化的只是房子的组成部分,这时我们可以考虑采用建造者模式来完成具体房屋的创建工作,即创建房屋和使用房屋责任的分离,房屋的构建与其表示相分离。同样的建造过程可以创建不同的表示(居民住房,存放货物的仓储房等)。

     本案例中的类与建造者模式中的角色的对应关系:

BuildingBuilder(房屋建造者)——Builder(抽象建造者)

Architect(建造师)——Director(导演者)

HousingBuilder(住房建造者)——ConcreteBuilder1(具体建造者1)

StorageBuilder(仓储房建造者)——ConcreteBuilder2(具体建造者2)

Building(房子)——Product(产品)

     实现的代码如下:

Project code using Abstract Factory in C#

输出结果为:


Building Type : Housing
Base : Housing Base
Wall : Housing Wall
#Windows : 2
#Doors : 2
#Rooms : 3
Floor : 3*20m2

Building Type : Storage
Base : Storage Base
Wall : Storage Wall
#Windows : 0
#Doors : 1
#Rooms : 0
Floor : 1000m2

     小结

1、Builder模式主要用于“分步骤构建一个复杂的对象”。在这其中“分步骤”是稳定的,而复杂对象的各个部分则经常变化。
2、Builder模式主要在于应对“复杂对象各个部分”的频繁需求变动。其缺点在于难以应对“分步骤构建算法”的需求变动。
3、Abstract Factory模式解决“系列对象”的需求变化,Builder模式解决“对象部分”的需求变化。Builder械通常和Composite模式组合使用。

      Welcome to share our idea,thank you!欢迎分享您的想法,谢谢!

      大家一起学面向对象设计模式系列 索引贴