Builder模式

来自KlniuWiki
跳转到: 导航, 搜索

目录

1 问题

生活中有着很多的Builder的例子,个人觉得大学生活就是一个Builder模式的最好体验:要完成大学教育,一般将大学教育过程分成4个学期进行,因此学习可以看作是构建完整大学教育的一个部分构建过程,每个人经过这4年的(4个阶段)构建过程得到的最后的结果不一样,因为可能在四个阶段的构建中引入了很多的参数(每个人的机会和际遇不完全相同)。

Builder模式要解决的也正是这样的问题:当我们要创建的对象很复杂的时候(通常是由很多其他的对象组合而成),我们要将复杂对象的创建过程和这个对象的表示(展示)分离开来,这样做的好处就是通过一步步的进行复杂对象的构建,由于在每一步的构造过程中可以引入参数,使得经过相同的步骤创建最后得到的对象的展示不一样。

2 模式选择

Builder模式的典型结构图为:

图1:Builder Pattern结构图

builder-pattern01.gif

Builder:为创建一个Product对象的各个部件制定抽象接口。

ConcreteBuilder:具体的建造者,它负责真正的生产。

Director:导演, 建造的执行者,它负责发布命令。

Product:最终消费的产品。

各类之间的交互关系如下图所示:

builder-pattern02.gif

Builder模式的关键是其中的Director对象并不直接返回对象,而是通过一步步(BuildPartA,BuildPartB,BuildPartC)来一步步进行对象的创建。当然这里Director可以提供一个默认的返回对象的接口(即返回通用的复杂对象的创建,即不指定或者特定唯一指定BuildPart中的参数)。

下面我们举个例子来加深我们对Builder模式的理解。 比如我们要通过一个汽车加工厂,生产一辆汽车;汽车由车轮 方向盘 发动机还有各种小零件等等组成,它的基本组装步骤是:

  • 生产车轮
  • 生产方向盘
  • 生产发动机
  • .................


通过上面的分析,我们知道,该范例满足Builder模式的应用场景所提到的条件:

  • 对象的创建:我们需要创建汽车对象
  • 创建的是一个复合对象:我们需要创建的汽车对象是具有车轮 方向盘 发动等复合属性的复合对象


下面我们用Builder设计模式来抽象以上组装过程:

  • Client:买汽车的顾客。通过向Director申请,然后Director让Builder组装汽车
  • Director:负责生产汽车的经理,或者销售人员
  • Builder:汽车组装抽象类
  • ConcreteBuilder:生产汽车的直接员工

3 示例代码

namespace DesignPattern_Builder
{
    class Product1 { /*...*/ } ;
    class Product2 { /*...*/ } ;
 
    // class Builder
    class Builder //抽象基类
    {
        public:
            virtual void BuilderPartA() {} //提供缺省实现
            virtual void BuilderPartB() {}
            virtual void BuilderPartC() {}
        protected:
            Builder() {}
    } ;
 
    // class ConcreteBuilder1
    class ConcreteBuilder1 : public Builder //创建Product1
    {
        public:
            ConcreteBuilder1() : _product(NULL) {}
 
            virtual void BuilderPartA() { /*...*/ } 
            virtual void BuilderPartB() { /*...*/ }
            virtual void BuilderPartC() { /*...*/ }
 
            virtual Product1* GetProduct1() { return _product ; } //返回创建的Product1对象
        private:
            Product1 *_product ;
    } ;
 
    // class ConcreteBuilder2
    class ConcreteBuilder2 : public Builder //创建Product2
    {
        public:
            ConcreteBuilder2() : _product(NULL) {}
 
            virtual void BuilderPartA() { /*...*/ } 
            virtual void BuilderPartB() { /*...*/ }
            virtual void BuilderPartC() { /*...*/ }
 
            virtual Product2* GetProduct2() { return _product ; } //返回创建的Product2对象
        private:
            Product2 *_product ;
    } ;
 
    // class Director
    class Director
    {
        public:
            //创建对象(Director并不知道具体创建出来的对象是什么样的,只有调用该函数的client知道)
            void Construct(Builder *builder)
            {
                builder->BuilderPartA() ;
                builder->BuilderPartB() ;
                builder->BuilderPartC() ;
            }
    } ;
}

客户端代码:

{
    using namespace DesignPattern_Builder ;
 
    Director director ;
 
    // 创建第一种对象
    ConcreteBuilder1 *pBuilder1 = new ConcreteBuilder1() ;
    director.Construct(pBuilder1) ;
    Product1 *product1 = pBuilder1->GetProduct1() ;
 
    // 创建第二种对象
    ConcreteBuilder2 *pBuilder2 = new ConcreteBuilder2() ;
    director.Construct(pBuilder2) ;
    Product2 *product2 = pBuilder2->GetProduct2() ;
}

4 实例

例子一。如下图所示:

builder-pattern03.gif

上图的功能是是把一个RTF文件转换为多种正文格式。RTFReader进行语法分析,然后将所有的token串逐一转换。可见builder就是一步步地把各个部分组装为一个整体。它封闭了组装的方法,组装出来的对象也大相径庭。

5 讨论

GoF在《设计模式》一书中给出的关于Builder模式的意图是非常容易理解、间接的:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示(在示例代码中可以通过传入不同的参数实现这一点)。

Builder模式和AbstractFactory模式在功能上很相似,因为都是用来创建大的复杂的对象,它们的区别是:Builder模式强调的是一步步创建对象,并通过相同的创建过程可以获得不同的结果对象,一般来说Builder模式中对象不是直接返回的。而在AbstractFactory模式中对象是直接返回的,AbstractFactory模式强调的是为创建多个相互依赖的对象提供一个同一的接口。

6 参见

个人工具
分类
化学
[×] 國學
学佛
[×] 数学
物理
生活
[×] 英语
读书
辞典
廣告