• 设计模式之建造者模式


    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),并将其添加到客户代码的调用中即可。

  • 相关阅读:
    swiper 增加一个鼠标移入分页器的小点后就切换展示图片
    css中的单冒号和双冒号 以及 伪类和伪元素
    pointer-events: none;元素永远不会成为鼠标事件的target
    jQuery off() 方法
    jQuery方法汇总
    vue 数组修改 页面无法刷新
    mysql error Code 1441:datetime function: datetime field overflow
    生命的意义
    删除镜像或容器
    nginx Redis 不能访问问题
  • 原文地址:https://www.cnblogs.com/ToBeExpert/p/9671158.html
Copyright © 2020-2023  润新知