设计模式(c++)笔记之四(Builder 模式)

    一、描述

    

      建造者模式,将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。一段晦涩难懂的文字,实现创建不同表示的方法就是给创建的过程传入创建的参数。

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


Builder 模式的典型结构图为: 



图 2-1:Builder Pattern 结构图


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


二、实例


1.例子描述:

  

    又是一个周三,快要下班了,老大突然又拉住我,喜滋滋的告诉我“牛叉公司很满意我们做的模型,又签订了一个合同,把奔驰、宝马的车辆模型都交给我我们公司制作了,不过这次又额外增加了一个新需求:汽车的启动、停止、喇叭声音、引擎声音都有客户自己控制,他想什么顺序就什么顺序,这个没问题吧?”。

    看着老大殷切的目光,我还能说啥,肯定的点头,“没问题!”,加班加点做呗,“再苦再累就当自己二百五 再难再险就当自己二皮脸 与君共勉!”这句话说出了我的心声。那任务是接下来,我们怎么做实现呢?首先我们想了,奔驰、宝马都是一个产品,他们有共有的属性,牛叉公司关心的是单个模型,奔驰模型 A 是先有引擎声音,然后再启动;奔驰模型 B 呢是先启动起来,然后再有引擎声音,这才是牛叉公司要关关心的,那到我们老大这边呢,就是满足人家的要求,要什么顺序就立马能产生什么顺序的模型出来,我呢就负责把老大的要求实现掉,而且还要是批量的,看不懂?没关系,继续看下去,首先由我生产出 N多个奔驰和宝马车辆模型,这些车辆模型的都有 run 方法,但是具体到每一个模型的 run 方法可能中间的执行任务的顺序是不同的,老大说要啥顺序,我就给啥顺序,最终客户买走后只能是既定的模型。先看类图: 




注释:

    main(),客户

    CCarModel,产品模型

    CBenzModel,奔驰模型

    CBMWModel,宝马模型

    ICarBuilder,建造者接口

    CBenzBuilder,奔驰建造者

    CBMWBuilder,宝马建造者

    CDirector,导演

说明:CCarModel实现模板方法,Builder负责开始建造产品。建造产品时,构建的顺序由Director或main决定。

注意:建造者模式和抽象工厂非常类似。建造者更重视产品建造时的逻辑顺序,而抽象工厂更重视生产出不同型号的产品,抽象工厂不关心顺序。


2.本人工程目录


      


3.代码

定义一个车辆模型的抽象类,所有的车辆模型都继承这里类 ,命名为CarModel

CarModel.h

//
//  CarModel.h
//  Builder
//
//  Created by IDEA-MAC03 on 13-10-15.
//  Copyright (c) 2013年 IDEA-MAC03. All rights reserved.
//

#ifndef __Builder__CarModel__
#define __Builder__CarModel__

#include <iostream>
#include <vector>
using std::vector;
using std::string;

class CCarModel
{
public:
    CCarModel(void);
    virtual ~CCarModel(void);
    void Run();
    void SetSequence(vector<string> *pSeq);
protected:
    virtual void Start() = 0;
    virtual void Stop() = 0;
    virtual void Alarm() = 0;
    virtual void EngineBoom() = 0;
private:
    vector<string> *m_pSequence;
};

#endif /* defined(__Builder__CarModel__) */
CarModel.cpp

#include "CarModel.h"
CCarModel::CCarModel(void){}

CCarModel::~CCarModel(){};

void CCarModel::SetSequence(vector<string> *pSeq)
{
    m_pSequence = pSeq;
}

void CCarModel::Run()
{
    vector<string>::const_iterator it = m_pSequence->begin();
    for (; it<m_pSequence->end(); ++it) {
        string actionName = *it;
        if (actionName.compare("start")==0)
        {
            Start();
        }
        else if(actionName.compare("stop") == 0)
        {
            Stop();
        }
        else if(actionName.compare("alarm") == 0)
        {
            Alarm();
        }
        else if(actionName.compare("engine boom") == 0)
        {
            EngineBoom();
        }
    }
}

run 方法使用了一个数组的遍历,确定那个是先执行,程序比较简单,不多说了,我们继续看两个实现类, 宝马类(BenzModel).奔驰类(BMWModel)

BenzModel.h

#ifndef __Builder__BenzModel__
#define __Builder__BenzModel__

#include <iostream>
#include "CarModel.h"
class CBenzModel:public CCarModel
{
public:
    CBenzModel(void);
    ~CBenzModel(void);
protected:
    void Start();
    void Stop();
    void Alarm();
    void EngineBoom();
};

#endif /* defined(__Builder__BenzModel__) */
BenzModel.cpp

#include "BenzModel.h"
using std::cout;
using std::endl;

CBenzModel::CBenzModel(void){}

CBenzModel::~CBenzModel(void){}

void CBenzModel::Start()
{
    cout << "奔驰发动..." << endl;
}

void CBenzModel::Stop()
{
    cout << "奔驰停车..." << endl;
}

void CBenzModel::Alarm()
{
    cout << "奔驰鸣笛" << endl;
}
void CBenzModel::EngineBoom()
{
    cout << "奔驰引擎声音是这样...." << endl;
}

BMWModel.h

#ifndef __Builder__BMWModel__
#define __Builder__BMWModel__

#include <iostream>
#include "CarModel.h"
class CBMWModel:public CCarModel
{
public:
    CBMWModel(void);
    ~CBMWModel(void);
protected:
    void Start();
    void Stop();
    void Alarm();
    void EngineBoom();
};

#endif /* defined(__Builder__BMWModel__) */
BMWModel.cpp

#include "BMWModel.h"
using std::cout;
using std::endl;

CBMWModel::CBMWModel(void)
{
}
CBMWModel::~CBMWModel(void)
{
}
void CBMWModel::Start()
{
    cout << "宝马发动..." << endl;
}
void CBMWModel::Stop()
{
    cout << "宝马停车..." << endl;
}
void CBMWModel::Alarm()
{
    cout << "宝马鸣笛" << endl;
}
void CBMWModel::EngineBoom()
{
    cout << "宝马引擎声音是这样...." << endl;
}

增加了一个 ICarBuilder 的抽象类,以及两个实现类,其目的是你要什么排列顺序的车,我就给你什么顺序的车.

ICarBuilder.h

#ifndef __Builder__ICarBuilder__
#define __Builder__ICarBuilder__

#include <iostream>
#include "CarModel.h"
#include <vector>
using std::string;
using std::vector;

class ICarBuilder
{
public:
    ICarBuilder(void){}
    virtual ~ICarBuilder(void){}
    virtual void SetSequence(vector<std::__1::string> *pseq) = 0;
    virtual CCarModel *GetCarModel() = 0;
    
};

#endif /* defined(__Builder__ICarBuilder__) */

我们按照一定的顺序制造一个宝马车

BenzBuilder.h

#ifndef __Builder__BenzBuilder__
#define __Builder__BenzBuilder__

#include <iostream>
#include "ICarBuilder.h"
#include "CarModel.h"
#include <iostream>
#include <vector>

using std::string;
using std::vector;
class CBenzBuilder:public ICarBuilder
{
public:
    CBenzBuilder(void);
    ~CBenzBuilder(void);
    void SetSequence(vector<string> *pSeq);
    CCarModel * GetCarModel();
private:
    CCarModel *m_pBenz;
};

#endif /* defined(__Builder__BenzBuilder__) */
BenzBuilder.cpp

#include "BenzBuilder.h"
#include "BenzModel.h"

CBenzBuilder::CBenzBuilder(void)
{
    m_pBenz = new CBenzModel();
}
CBenzBuilder::~CBenzBuilder(void)
{
    delete m_pBenz;
}
void CBenzBuilder::SetSequence(vector<string> *pSeq)
{
    m_pBenz->SetSequence(pSeq);
}
CCarModel * CBenzBuilder::GetCarModel()
{
    return m_pBenz;
}

我们按照一定的顺序制造一个奔驰车

BMWBuilder.h

#ifndef __Builder__BMWBuilder__
#define __Builder__BMWBuilder__

#include <iostream>
#include "ICarBuilder.h"
#include "CarModel.h"
#include <vector>
using std::string;
using std::vector;

class CBMWBuilder:public ICarBuilder
{
public:
    CBMWBuilder(void);
    ~CBMWBuilder(void);
    void SetSequence(vector<string> *pSeq);
    CCarModel * GetCarModel();
private:
    CCarModel *m_pBMW;
    
};

#endif /* defined(__Builder__BMWBuilder__) */
BMWBuilder.cpp

#include "BMWBuilder.h"
#include "BMWModel.h"

CBMWBuilder::CBMWBuilder(void)
{
    m_pBMW = new CBMWModel();
}
CBMWBuilder::~CBMWBuilder(void)
{
    delete m_pBMW;
}
void CBMWBuilder::SetSequence( vector<string> *pSeq )
{
    m_pBMW->SetSequence(pSeq);
}
CCarModel * CBMWBuilder::GetCarModel()
{
    return m_pBMW;
}

增加了 Director 类,这个类是做了层封装,类中的方法说明如下:
A 型号的奔驰车辆模型是只有启动(start)、停止(stop)方法,其他的引擎声音、喇叭都没有;
B 型号的奔驰车是先发动引擎(engine boom),然后启动(star),再然后停车(stop),没有喇叭;
C 型号的宝马车是先喇叭叫一下(alarm),然后(start),再然后是停车(stop),引擎不轰鸣;
D 型号的宝马车就一个启动(start),然后一路跑到黑,永动机,没有停止方法,没有喇叭,没有引擎轰鸣;E 型号、F 型号...等等,可以有很多,启动(start)、停止(stop)、喇叭(alarm)、引擎轰鸣(engine boom) 

Director.h

#include "BenzBuilder.h"
#include "BMWBuilder.h"

#include <vector>
class CDirector
{
public:
    CDirector(void);
    ~CDirector(void);
    CBenzModel *GetABenzModel();
    CBenzModel * GetBBenzModel();
    CBMWModel * GetCBMWModel();
    CBMWModel * GetDBMWModel();
private:
    vector<string> *m_pSeqence;
    CBenzBuilder *m_pBenzBuilder;
    CBMWBuilder *m_pBMWBuilder;

};


#endif /* defined(__Builder__Director__) */
Director.cpp

#include "Director.h"

CDirector::CDirector(void)
{
    m_pBenzBuilder = new CBenzBuilder();
    m_pBMWBuilder = new CBMWBuilder();
    m_pSeqence = new vector<string>();
}

CDirector::~CDirector()
{
    delete m_pBenzBuilder;
    delete m_pBMWBuilder;
    delete m_pSeqence;
}

CBenzModel * CDirector::GetABenzModel()
{
    m_pSeqence->clear();
    m_pSeqence->push_back("start");
    m_pSeqence->push_back("stop");
    m_pBenzBuilder->SetSequence(m_pSeqence);
    return dynamic_cast<CBenzModel*>(m_pBenzBuilder->GetCarModel());
}

CBenzModel * CDirector::GetBBenzModel()
{
    m_pSeqence->clear();
    m_pSeqence->push_back("engine boom");
    m_pSeqence->push_back("start");
    m_pSeqence->push_back("stop");
    m_pBenzBuilder->SetSequence(m_pSeqence);
    return dynamic_cast<CBenzModel*>(m_pBenzBuilder->GetCarModel());
}

CBMWModel * CDirector::GetCBMWModel()
{
    m_pSeqence->clear();
    m_pSeqence->push_back("alarm");
    m_pSeqence->push_back("start");
    m_pSeqence->push_back("stop");
    m_pBMWBuilder->SetSequence(m_pSeqence);
    return static_cast<CBMWModel*>(m_pBMWBuilder->GetCarModel());
}

CBMWModel * CDirector::GetDBMWModel()
{
    m_pSeqence->clear();
    m_pSeqence->push_back("start");
    m_pBenzBuilder->SetSequence(m_pSeqence);
    return dynamic_cast<CBMWModel*>(m_pBMWBuilder->GetCarModel());
}

测试代码

main.cpp

//
//  main.c
//  Builder
//
//  Created by IDEA-MAC03 on 13-10-15.
//  Copyright (c) 2013年 IDEA-MAC03. All rights reserved.
//

#include <stdio.h>
#include "CarModel.h"
#include "BenzModel.h"
#include "BMWModel.h"
#include "BenzBuilder.h"
#include "BMWBuilder.h"
#include "Director.h"
#include <vector>
#include <iostream>
using std::vector;
using std::string;
using std::cout;
using std::endl;

void DoBenzRun()
{
    cout << "----------生成奔驰模型----------" << endl;
    CBenzModel *pBenz = new CBenzModel();
    vector<string> seq;
    seq.push_back("engine boom");//客户要求run的时候先发动引擎
    seq.push_back("start");//启动起来
    seq.push_back("stop");//开了一段就停下来
    
    pBenz->SetSequence(&seq);
    pBenz->Run();
    delete pBenz;
}

void DoBuilder()
{
    cout << "----------用同一个顺序,生成模型----------" << endl;
    vector<string> seq;
    seq.push_back("engine boom");
    seq.push_back("start");
    seq.push_back("stop");
    
    CBenzBuilder benzBuilder;
    benzBuilder.SetSequence(&seq);
    CBenzModel *pBenz = dynamic_cast<CBenzModel*>(benzBuilder.GetCarModel());
    pBenz->Run();
    
    CBMWBuilder bmwBuilder;
    bmwBuilder.SetSequence(&seq);
    CBMWModel *pBmw = dynamic_cast<CBMWModel*>(bmwBuilder.GetCarModel());
    pBmw->Run();
}

void DoDirector()
{
    cout << "----------批量生成模型----------" << endl;
    CDirector director;
    
    //1W辆A类型的奔驰车
    cout<< "1W辆A类型的奔驰车:" <<endl;
    for(int i = 0; i < 1; i++)
        director.GetABenzModel()->Run();
    
    cout<< "100W辆B类型的奔驰车:" <<endl;
    //100W辆B类型的奔驰车
    for(int i = 0; i < 1; i++)
        director.GetBBenzModel()->Run();
    
    
     cout<< "1000W辆C类型的宝马车:" <<endl;
    //1000W辆C类型的宝马车
    for(int i = 0; i < 1; i++)
        director.GetCBMWModel()->Run();
}

int main(int argc, const char * argv[])
{
    
    DoBenzRun();
    DoBuilder();
    DoDirector();
    // insert code here...
    printf("Hello, World!\n");
    return 0;
}

结果如下:


参考文献:《设计模式之禅》,《GoF_23种设计模式解析》

参考博客:http://www.cnblogs.com/wanggary/archive/2011/04/15/2017615.html

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
Builder模式 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示 统设计中,有时候面临着一个“复杂系统”的创建工作,该对象通常由各个部分的子对象用一定的算法构成,或者说按一定的步骤组合而成;这些的算法和步骤是稳定的,而构成这个对象的子对象却经常由于需求改变而发生变化,此时我们可以选择使用Builder模式。尽管Builder模式相当容易让人误解,但我认为这几点应该是不会有错的。因此我个人认为Builder模式中要好好把握如下几点 1. 需要创建的对象是复杂对象 2. 对象的创建过程是一步步创建(即:可能由于过程的不同而导致有不同的对象展示) 3. 明确建造者(Builder)、具体建造者(Concrete Builder)、指导者(Director)、产品(Product)之间的职责和联系。 ◆建造者(Builder): 给出一个抽象接口,以规范产品对象的各个组成成分的建造。一般而言,此接口独立于应用程序的商业逻辑。模式中直接创建产品对象的是 具体建造者(ConcreteBuilder):具体建造者类必须实现这个接口所要求的方法:一个是建造方法,另一个是结果返还方法。 ◆具体建造者(Concrete Builder): 担任这个角色的是于应用程序紧密相关的类,它们在应用程序调用下创建产品实例。这个角色主要完成的任务包括: ■实现Builder角色提供的接口,一步一步完成创建产品实例的过程。 ■在建造过程完成后,提供产品的实例。 ◆指导者(Director): 担任这个角色的类调用具体建造者角色以创建产品对象。导演者并没有产品类的具体知识,真正拥有产品类的具体知识的是具体建造者对象。 ◆产品(Product): 产品便是建造中的复杂对象。 详细见博客 http://blog.csdn.net/xiaoting451292510/article/details/8330462

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

热血枫叶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值