设计模式之建造者模式

2018-09-18 22:19:07

依赖倒转原则

  高层模块不依赖低层模块,二者都不依赖细节。抽象不应该依赖细节,细节应该依赖于抽象。这句话什么意思呢,就是说你有一个虚基类(抽象),这个基类每一个方法都有明确的含义,稳定的传参形式和返回类型。不管子类如何实现这些方法(细节),只要完成了基类要求的功能即可。

建造者模式

  如果,你需要将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示时,此时就需要建造者模式(Builder)又叫做生成器模式。建造者模式可以将一个产品内部表象与产品的生成过程分隔开来,从而可以使一个建造过程具有不同的内部表象的产品对象。如果我们用了建造者模式,那么用户就只需要指定需要建造的类型就可以得到它们,而具体的建造过程和细节就不需要知道了。

  建造者(Builder)模式:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

  使用建造者流程:1.抽象出一个稳定的建造流程(就是一个包含一些列方法的虚基类咯);

          2.当需要构建一个符合这个建造流程的对象时,我们只需要从虚基类中派生出一个子类,子类按照自己的特殊要求去实现基类的方法即可。

          3.构建指挥者(Director)类,这在建造者模式中是非常重要的一个类,用它来控制建造流程,也用它来隔离用户与建造过程的关联。实际上就是根据用户的选择来建造他需要的类。而建造的过程是用户不需要关心的。

建造者UML图

  其中:Builder是一个创建产品的流程提供者(虚基类),它指定了创建一个Product对象的各个部件的抽象接口。

     ConcreteBuilder是具体建造者,实现Builder接口,构造和装配各个部件。Product就是具体的产品角色了。

     Director是构建一个使用Builder接口的对象。

  建造者模式的使用场景:主要用于创建一些复杂的对象,这些对象内部构建间的顺序通常是稳定的,但对象内部的构建通常面临着复杂的变化。使用建造者模式的好处是,使得建造代码与表示代码分离,由于建造者隐藏了该产品是如何组装的,所以若需要改变一个产品的内部表示,只需要再定义一个具体的建造者就可以了。

代码实现

1.要构建的类:

#ifndef PRODUCT_H_
#define PRODUCT_H_
#include <vector>
#include <string>
#include <iostream>
class Product
{
public:
    void addPart(const std::string strPart);
    void show();
    Product() = default;
    ~Product() = default;
private:
    std::vector<std::string> m_vecPart;
};
#endif

#include "Product.h"

void Product::addPart(const std::string strPart)
{
    m_vecPart.push_back(strPart);
}

void Product::show()
{
   for(auto value : m_vecPart)
   {
    std::cout << value << std::endl;
   }
}
Product

2.抽象建造者(Builder)

#ifndef BUILDER_H_
#define BUILDER_H_
#include <string>
class Builder
{
public:
    virtual void buildPartA(const std::string strPartA) = 0;
    virtual void buildPartB(const std::string strPartB) = 0;
    virtual void buildPartC(const std::string strPartC) = 0;
    virtual void buildPartD(const std::string strPartD) = 0;
    virtual void getResult() = 0;
    Builder() = default;
    virtual ~Builder() = default;
};
#endif
Builder

3.具体建造者(Concrete Builder)

#ifndef CONCRETEBUILDER1_H_
#define CONCRETEBUILDER1_H_
#include "Builder.h"
#include "Product.h"
class ConcreteBuilder1:public Builder
{
public:
    void buildPartA(const std::string strPartA) override;
    void buildPartB(const std::string strPartB) override;
    void buildPartC(const std::string strPartC) override;
    void buildPartD(const std::string strPartD) override;
    void getResult() override;
    ConcreteBuilder1() = default;
    ~ConcreteBuilder1() = default;
private:
    Product m_myProduct;
};
#endif

#include "ConcreteBuilder1.h"

void ConcreteBuilder1::buildPartA(const std::string strPartA)
{
    m_myProduct.addPart(strPartA);
}

void ConcreteBuilder1::buildPartB(const std::string strPartB)
{
    m_myProduct.addPart(strPartB);
}

void ConcreteBuilder1::buildPartC(const std::string strPartC)
{
    m_myProduct.addPart(strPartC);
}

void ConcreteBuilder1::buildPartD(const std::string strPartD)
{
    m_myProduct.addPart(strPartD);
}

void ConcreteBuilder1::getResult() 
{
    m_myProduct.show();
}

4.建造的指挥者(Director)也是建造者模式的核心类

#ifndef DIRECTOR_H_
#define DIRECTOR_H_
#include "Builder.h"
class Director
{
public:
    void construct(Builder* builder);
    Director() = default;
    ~Director() = default;
};
#endif 

#include "Director.h"
void Director::construct(Builder* builder)
{
    builder->buildPartA("This is a C++ Program!");
    builder->buildPartB("This is a Builder Model");
    builder->buildPartC("Hello ");
    builder->buildPartD("Could you understand");
}
Director

5.main函数

#include "Director.h"
#include "Builder.h"
#include "ConcreteBuilder1.h"

using namespace std;

int main(int argc,char *argv[])
{
    Director myDirector;
    Builder *myBuilder = new ConcreteBuilder1;
    myDirector.construct(myBuilder);
    myBuilder->getResult();
    if(nullptr != myBuilder)
    {
    delete myBuilder;
        myBuilder=nullptr;
    }
    return(1);
}
main

  根据上面的示例代码,如果我们想构建新的Product的实例,那么只需要新增一个具体建造者(Concrete Bulider),并将其添加到客户代码的调用中即可。

posted on 2018-09-18 22:19  古I月  阅读(203)  评论(0编辑  收藏  举报

导航