【设计模式】建造者模式

烂漫一生 提交于 2020-01-14 08:23:16

1、定义

1.1 标准定义

  建造者模式( Builder Pattern) 也叫做生成器模式, 其定义如下:

  Separate the construction of a complex object from its representation so that the same construction process can create different representations.( 将一个复杂对象的构建与它的表示分离, 使得同样的构建过程可以创建不同的表示。 )

1.2  通用类图

  在建造者模式中, 有如下4个角色:

  ● Product产品类
  通常是实现了模板方法模式, 也就是有模板方法和基本方法, 参考模板方法模式。

  ● Builder抽象建造者
  规范产品的组建, 一般是由子类实现。

  ● ConcreteBuilder具体建造者
  实现抽象类定义的所有方法, 并且返回一个组建好的对象。

  ● Director导演类
  负责安排已有模块的顺序。

2、实现

2.1 类图

  Builder:定义创建对象过程的抽象,提供构建不同组成部分的接口

  其中:BuildPartA,BuildPartB,BuildPartC是对一个对象不同部分的构建函数接口,由Builder的派生类ConcreteBuilder1、ConcreteBuilder2来具体实现。

  另外还有一个需要注意的函数,就是Director::Construct函数,这个函数里面通过调用上面的接口函数完成对象的构建--也就是说各个不同部分装配的过程都是一致的(同样的调用的Construct函数),但是不同的构建方式会有不同的表示(根据Builder的实际类型来决定如何构建,也就是多态)。

  Builder模式是基于这样的一个情况:一个对象可能有不同的组成部分,这几个部分的不同的创建对象会有不同的表示,但是各个部分之间装配的方式是一致的.比方说一辆单车,都是由车轮车座等等的构成的(一个对象不同的组成部分),不同的品牌生产出来的也不一样(不同的构建方式).虽然不同的品牌构建出来的单车不同,但是构建的过程还是一样的。

  也就是说,Director::Construct函数中固定了各个组成部分的装配方式,而具体是装配怎样的组成部分由Builder的派生类实现.

2.2 代码

2.2.1 建造者

//builder.h

#ifndef _BUILDER_H_
#define _BUILDER_H_

#include <string>
#include <vector>

using namespace std;

//产品类
class Product
{
private:
    string m_partA;
    string m_partB;
    string m_partC;
public:
    void setPartA(const string& s);
    void setPartB(const string& s);
    void setPartC(const string& s);
    Product();
    ~Product();
};

//抽象Builder基类,定义不同部分的创建接口
class Builder
{
public:
    virtual void BuildPartA()=0;
    virtual void BuildPartB()=0;
    virtual void BuildPartC()=0;
    virtual Product* GetProduct()=0;
    Builder();
    virtual ~Builder();
};

//  Builder的派生类,实现BuilderPartA和BuilderPartB和BuildPartC接口函数 
class ConcreteBuilder1:public Builder
{
public:
    ConcreteBuilder1();
    ~ConcreteBuilder1();
    virtual void BuildPartA();
    virtual void BuildPartB();
    virtual void BuildPartC();
    virtual Product* GetProduct();
private:
    Product* m_pProduct;
};

//  Builder的派生类,实现BuilderPartA和BuilderPartB和BuildPartC接口函数 
class ConcreteBuilder2:public Builder
{
public:
    ConcreteBuilder2();
    ~ConcreteBuilder2();
    virtual void BuildPartA();
    virtual void BuildPartB();
    virtual void BuildPartC();
    virtual Product* GetProduct();
private:
    Product* m_pProduct;
};

//ConcreteBuilder1与ConcreteBuilder2是Builder的两个派生类,用于实现两种不同的建造细节

 // 使用Builder构建产品,构建产品的过程都一致,但是不同的builder有不同的实现
 // 这个不同的实现通过不同的Builder派生类来实现,存有一个Builder的指针,通过这个来实现多态调用 
class Director
{
public:
    Director(Builder* pBuilder);
    ~Director();

    //Construct函数定义一个对象的整个构建过程,不同的部分之间的装配方式都是一致的,
    //首先构建PartA其次是PartB,只是根据不同的构建者会有不同的表示 
    void Construct();
    //void Construct(const string& buildPara);
private:
    Builder* m_pBuilder;
};

#endif
//builder.cpp

#include "Builder.h"
#include <iostream>
#include <vector>

using namespace std;

Product::~Product(){}

Product::Product(){}

void Product::setPartA(const string& s)
{
    this->m_partA = s;
}

void Product::setPartB(const string& s)
{
    this->m_partB = s;
}

void Product::setPartC(const string& s)
{
    this->m_partC = s;
}

//--------------------------------------------

Builder::Builder(){}

Builder::~Builder(){}

//--------------------------------------------

ConcreteBuilder1::ConcreteBuilder1()
{
    this->m_pProduct = new Product();
    cout<<"Create empty product!"<<endl;
}

void ConcreteBuilder1::BuildPartA()
{
    this->m_pProduct->setPartA("A");
    cout<<"BuildPartA"<<endl;
}

void ConcreteBuilder1::BuildPartB()
{
    this->m_pProduct->setPartB("B");
    cout<<"BuildPartB"<<endl;
}

void ConcreteBuilder1::BuildPartC()
{
    this->m_pProduct->setPartC("C");
    cout<<"BuildPartC"<<endl;
}

Product* ConcreteBuilder1::GetProduct()
{
    return this->m_pProduct;
}

ConcreteBuilder1::~ConcreteBuilder1()
{
    delete this->m_pProduct;
    this->m_pProduct = NULL;
}

//--------------------------------------------

ConcreteBuilder2::ConcreteBuilder2()
{
    this->m_pProduct = new Product();
    cout<<"Create empty product!"<<endl;
}

void ConcreteBuilder2::BuildPartA()
{
    this->m_pProduct->setPartA("A");
    cout<<"BuildPartA"<<endl;
}

void ConcreteBuilder2::BuildPartB()
{
    this->m_pProduct->setPartB("B");
    cout<<"BuildPartB"<<endl;
}

void ConcreteBuilder2::BuildPartC()
{
    this->m_pProduct->setPartC("C");
    cout<<"BuildPartC"<<endl;
}

Product* ConcreteBuilder2::GetProduct()
{
    return this->m_pProduct;
}

ConcreteBuilder2::~ConcreteBuilder2()
{
    delete this->m_pProduct;
    this->m_pProduct = NULL;
}

//--------------------------------------------

Director::Director(Builder* pBuilder)
{
    this->m_pBuilder = pBuilder;
}

void Director::Construct()
{
    this->m_pBuilder->BuildPartA();
    this->m_pBuilder->BuildPartB();
    this->m_pBuilder->BuildPartC();
}

Director::~Director()
{
    delete this->m_pBuilder;
    this->m_pBuilder = NULL;
}

2.2.3 调用

//main.cpp

#include "Builder.h"
#include <iostream>

using namespace std;

int main()
{
    Director* pDirector = new Director(new ConcreteBuilder1());
    pDirector->Construct();

    Director* pDirector1 = new Director(new ConcreteBuilder2());
    pDirector1->Construct();
    
    delete pDirector;
    pDirector = NULL;
    
    delete pDirector1;
    pDirector1 = NULL;

    return 0;
}

3、优缺点

  ● 封装性
  使用建造者模式可以使客户端不必知道产品内部组成的细节。

  ● 建造者独立, 容易扩展
  各个Builder是相互独立的, 对系统的扩展非常有利。

  ● 便于控制细节风险
  由于具体的建造者是独立的, 因此可以对建造过程逐步细化, 而不对其他的模块产生任何影响。

4、使用场景

  ● 相同的方法, 不同的执行顺序, 产生不同的事件结果时, 可以采用建造者模式。
  ● 多个部件或零件, 都可以装配到一个对象中, 但是产生的运行结果又不相同时, 则可以使用该模式。
  ● 产品类非常复杂, 或者产品类中的调用顺序不同产生了不同的效能, 这个时候使用建造者模式非常合适。

5、Builder VS AbstractFactory

  建造者模式最主要的功能是基本方法的调用顺序安排, 也就是这些基本方法已经实现了, 通俗地说就是零件的装配, 顺序不同产生的对象也不同; 而工厂方法则重点是创建, 创建零件是它的主要职责, 组装顺序则不是它关心的。

  Builder模式强调的是一步步创建对象,并通过相同的创建过程可以获得不同的结果对象,一般来说Builder模式中对象不是直接返回的。而在AbstractFactory模式中对象是直接返回的,AbstractFactory模式强调的是为创建多个相互依赖的对象提供一个同一的接口。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!