c++ 设计模式:建造者模式

建造者模式(Builder Pattern)是一种创建型设计模式,它允许你构造复杂对象步骤分解。你可以不同的步骤中使用不同的方式创建对象,且对象的创建与表示是分离的。这样,同样的构建过程可以创建不同的表示。

举例说明:

#include <iostream>
//#include <map>
//#include <stack>
#include <vector>
#include <sstream>

#ifdef _DEBUG   //只在Debug(调试)模式下
#ifndef DEBUG_NEW
#define DEBUG_NEW new(_NORMAL_BLOCK,__FILE__,__LINE__) //重新定义new运算符
#define new DEBUG_NEW
#endif
#endif

//#include <boost/type_index.hpp>
using namespace std;
//#pragma warning(disable : 4996) 

namespace _nmsp1
{
    //怪物父类
    class Monster
    {
    public:
        virtual ~Monster() {} //做父类时析构函数应该为虚函数
        //void Assemble(string strmodelno) //参数:模型编号,形如:“1253679201245”等。每些位的组合都有一些特别的含义,这里不需要探究。
        //{
        //    LoadTrunkModel(strmodelno.substr(4, 3)); //载入躯干模型,截取某部分字符串以表示躯干模型的编号
        //    LoadHeadModel(strmodelno.substr(7, 3)); //载入头部模型并挂接到躯干模型上
        //    LoadLimbsModel(strmodelno.substr(10, 3)); //载入四肢模型并挂接到躯干模型上
        //}

        //virtual void LoadTrunkModel(string strno) = 0; //这里也可以写成一个空函数,子类决定是否重新实现
        //virtual void LoadHeadModel(string strno) = 0;
        //virtual void LoadLimbsModel(string strno) = 0;
    };

    //亡灵类怪物
    class M_Undead :public Monster
    {
    /*public:
        virtual void LoadTrunkModel(string strno)
        {
            cout << "载入亡灵类怪物的躯干部位模型,需要调用M_Undead类或其父类中其他诸多成员函数,逻辑代码略......" << endl;
        }
        virtual void LoadHeadModel(string strno)
        {
            cout << "载入亡灵类怪物的头部模型并挂接到躯干部位,需要调用M_Undead类或其父类中其他诸多成员函数,逻辑代码略......" << endl;
        }
        virtual void LoadLimbsModel(string strno)
        {
            cout << "载入亡灵类怪物的四肢模型并挂接到躯干部位,需要调用M_Undead类或其父类中其他诸多成员函数,逻辑代码略......" << endl;
        }*/
    };

    //元素类怪物
    class M_Element :public Monster
    {
    /*public:
        virtual void LoadTrunkModel(string strno)
        {
            cout << "载入元素类怪物的躯干部位模型,需要调用M_Element类或其父类中其他诸多成员函数,逻辑代码略......" << endl;
        }
        virtual void LoadHeadModel(string strno)
        {
            cout << "载入元素类怪物的头部模型并挂接到躯干部位,需要调用M_Element类或其父类中其他诸多成员函数,逻辑代码略......" << endl;
        }
        virtual void LoadLimbsModel(string strno)
        {
            cout << "载入元素类怪物的四肢模型并挂接到躯干部位,需要调用M_Element类或其父类中其他诸多成员函数,逻辑代码略......" << endl;
        }*/
    };

    //机械类怪物
    class M_Mechanic :public Monster
    {
    /*public:
        virtual void LoadTrunkModel(string strno)
        {
            cout << "载入机械类怪物的躯干部位模型,需要调用M_Mechanic类或其父类中其他诸多成员函数,逻辑代码略......" << endl;
        }
        virtual void LoadHeadModel(string strno)
        {
            cout << "载入机械类怪物的头部模型并挂接到躯干部位,需要调用M_Mechanic类或其父类中其他诸多成员函数,逻辑代码略......" << endl;
        }
        virtual void LoadLimbsModel(string strno)
        {
            cout << "载入机械类怪物的四肢模型并挂接到躯干部位,需要调用M_Mechanic类或其父类中其他诸多成员函数,逻辑代码略......" << endl;
        }*/
    };
    //----------------------------
    //怪物构建器父类
    class MonsterBuilder
    {
    public:
        virtual ~MonsterBuilder() {} //做父类时析构函数应该为虚函数
        //void Assemble(string strmodelno) //参数:模型编号,形如:“1253679201245”等。每些位的组合都有一些特别的含义,这里不需要探究。
        //{
        //    LoadTrunkModel(strmodelno.substr(4, 3)); //载入躯干模型,截取某部分字符串以表示躯干模型的编号
        //    LoadHeadModel(strmodelno.substr(7, 3)); //载入头部模型并挂接到躯干模型上
        //    LoadLimbsModel(strmodelno.substr(10, 3)); //载入四肢模型并挂接到躯干模型上
        //}

        //返回指向Monster类的成员变量指针m_pMonster,当一个复杂的对象构建完成后,可以通过该成员函数把对象返回。
        Monster* GetResult()
        {
            return m_pMonster;
        }

        virtual void LoadTrunkModel(string strno) = 0; //这里也可以写成一个空函数,子类决定是否重新实现
        virtual void LoadHeadModel(string strno) = 0;
        virtual void LoadLimbsModel(string strno) = 0;

    protected:
        Monster* m_pMonster; //指向Monster类的成员变量指针
    };

    //----------
    //亡灵类怪物构建器类
    class M_UndeadBuilder :public MonsterBuilder
    {
    public:
        M_UndeadBuilder() //构造函数
        {
            m_pMonster = new M_Undead();
        }

        virtual void LoadTrunkModel(string strno)
        {
            cout << "载入亡灵类怪物的躯干部位模型,需要m_pMonster指针调用M_Undead类或其父类中其他诸多成员函数,逻辑代码略......" << endl;
            //具体要做的事情其实是委托给怪物子类完成,委托指把本该自己实现的功能转给其他类实现
            //m_pMonster->......略
        }
        virtual void LoadHeadModel(string strno)
        {
            cout << "载入亡灵类怪物的头部模型并挂接到躯干部位,需要m_pMonster指针调用M_Undead类或其父类中其他诸多成员函数,逻辑代码略......" << endl;
            //m_pMonster->......略
        }
        virtual void LoadLimbsModel(string strno)
        {
            cout << "载入亡灵类怪物的四肢模型并挂接到躯干部位,需要m_pMonster指针调用M_Undead类或其父类中其他诸多成员函数,逻辑代码略......" << endl;
            //m_pMonster->......略
        }
    };

    //元素类怪物构建器类
    class M_ElementBuilder :public MonsterBuilder
    {
    public:
        M_ElementBuilder() //构造函数
        {
            m_pMonster = new M_Element();
        }

        virtual void LoadTrunkModel(string strno)
        {
            cout << "载入元素类怪物的躯干部位模型,需要m_pMonster指针调用M_Element类或其父类中其他诸多成员函数,逻辑代码略......" << endl;            
            //m_pMonster->......略
        }
        virtual void LoadHeadModel(string strno)
        {
            cout << "载入元素类怪物的头部模型并挂接到躯干部位,需要m_pMonster指针调用M_Element类或其父类中其他诸多成员函数,逻辑代码略......" << endl;
            //m_pMonster->......略
        }
        virtual void LoadLimbsModel(string strno)
        {
            cout << "载入元素类怪物的四肢模型并挂接到躯干部位,需要m_pMonster指针调用M_Element类或其父类中其他诸多成员函数,逻辑代码略......" << endl;
            //m_pMonster->......略
        }
    };

    //机械类怪物构建器类
    class M_MechanicBuilder :public MonsterBuilder
    {
    public:
        M_MechanicBuilder() //构造函数
        {
            m_pMonster = new M_Mechanic();
        }

        virtual void LoadTrunkModel(string strno)
        {
            cout << "载入机械类怪物的躯干部位模型,需要m_pMonster指针调用M_Mechanic类或其父类中其他诸多成员函数,逻辑代码略......" << endl;
            //m_pMonster->......略
        }
        virtual void LoadHeadModel(string strno)
        {
            cout << "载入机械类怪物的头部模型并挂接到躯干部位,需要m_pMonster指针调用M_Mechanic类或其父类中其他诸多成员函数,逻辑代码略......" << endl;
            //m_pMonster->......略
        }
        virtual void LoadLimbsModel(string strno)
        {
            cout << "载入机械类怪物的四肢模型并挂接到躯干部位,需要m_pMonster指针调用M_Mechanic类或其父类中其他诸多成员函数,逻辑代码略......" << endl;
            //m_pMonster->......略
        }
    };

    //------------------
    //指挥者类
    class MonsterDirector
    {
    public:
        MonsterDirector(MonsterBuilder* ptmpBuilder) //构造函数
        {
            m_pMonsterBuilder = ptmpBuilder;
        }

        //指定新的构建器
        void SetBuilder(MonsterBuilder* ptmpBuilder)
        {
            m_pMonsterBuilder = ptmpBuilder;
        }

        //原MonsterBuilder类中的Assemble成员函数
        Monster *Construct(string strmodelno) //参数:模型编号,形如:“1253679201245”等。每些位的组合都有一些特别的含义,这里不需要探究。
        {
            m_pMonsterBuilder->LoadTrunkModel(strmodelno.substr(4, 3)); //载入躯干模型,截取某部分字符串以表示躯干模型的编号
            m_pMonsterBuilder->LoadHeadModel(strmodelno.substr(7, 3)); //载入头部模型并挂接到躯干模型上
            m_pMonsterBuilder->LoadLimbsModel(strmodelno.substr(10, 3)); //载入四肢模型并挂接到躯干模型上
            return m_pMonsterBuilder->GetResult(); //返回构建后的对象
        }
    private:
        MonsterBuilder* m_pMonsterBuilder; //指向所有构建器类的父类
    };
}
int main()
{

    /*
    _nmsp1::Monster* pmonster = new _nmsp1::M_Element(); //创建一只元素类怪物
    pmonster->Assemble("1253679201254");

    //释放资源
    delete pmonster;
    */
   
    _nmsp1::MonsterBuilder* pMonsterBuilder = new _nmsp1::M_UndeadBuilder(); //创建亡灵类怪物构建器对象
    _nmsp1::MonsterDirector* pDirector = new _nmsp1::MonsterDirector(pMonsterBuilder);
    _nmsp1::Monster* pMonster = pDirector->Construct("1253679201254"); //这里就构建出了一个完整的怪物对象

    //释放资源
    delete pMonster;
    delete pDirector;
    delete pMonsterBuilder;
   
}

建造者(Builder)模式

   构建器/构建者/生成器模式-创建型模式。
    通常用于创建比较复杂的对象
   (1)一个具体实现范例的逐步重构
          怪物:亡灵类,元素类,机械类
          怪物组成:头部、躯干(颈部、尾巴)、肢体 三个部位组成。
          编码步骤:将怪物躯干部模型信息读入内存。将怪物的头部和四肢模型信息读入内存。将头部和四肢模型以正确的位置和方向挂接到躯干部位。  最终装配出完整的怪物模型。
         Assemble、LoadTrunkModel、LoadHeadModel、LoadLimbsModel称为构建过程相关的函数。
         引入与怪物类同层次的相关构建器类,把怪物类中代码搬到相关的构建器类中。
(2)引入建造者(Builder)模式
         引入建造者(Builder)模式定义:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
          MonsterBuilder类就是对象的构建,Monster类是对象的表示。
    建造者模式包含四种角色:
      a)Builder(抽象构建器):这里指MonsterBuilder。
      b)ConcreteBuilder(具体构建器):这里指M_UndeadBuilder、M_ElementBuilder、M_MechanicBuilder类。
      c)Product(产品):这里指M_Undead、M_Element、M_Mechanic类。
      d)Director(指挥者):MonsterDirector类。
    复杂的东西就考虑拆解,简单的东西就考虑合并。
 
(4)建造者模式的总结:用于分步骤构建一个复杂对象,其中构建步骤是一个稳定算法(构建算法)。
        何时使用:
           a)产品对象内部结构复杂,产品往往由多个零件组成。
           b)需要创建的产品对象内部属性互相依赖,需要指定创建次序。
           c)当创建复杂对象的步骤(过程)应该独立于该对象的组成部分;
           d)将复杂对象的创建和使用分离,使相同的创建过程可以创建不同的产品。
       指挥者类作用:
          a)通过部件以指定的顺序来构建整个产品(控制了构建过程)
          b)通过提供Construct接口隔离了客户端与具体构建过程所必须要调用的类的成员函数之间的关联。
      建造者模式优点:
         a)产品构建和产品表现上的分离。构建算法可以被复用。
         b)向客户端隐藏了产品内部的表现。
        c)产品的实现可以被随时替换。
    建造者模式缺点:
       a)要求所创建的产品有比较多的共同点,创建步骤(组成部分)要大致相同。
       b)该模式涉及到很多类。Director,Builder对象。对于理解和学习具有一定门槛。
 
https://blog.csdn.net/weixin_42097108/article/details/133609448
 
posted @ 2024-05-24 17:16  白伟碧一些小心得  阅读(27)  评论(0编辑  收藏  举报