美文网首页
S2. 生成器模式

S2. 生成器模式

作者: 拂去尘世尘 | 来源:发表于2021-10-24 18:09 被阅读0次

    生成器模式

    生成器模式属于创建型设计模式,根据需要分步创建功能较多的对象。

    场景

    问题

    假设要生产两款不同品牌的笔记本ThinkPad X 13和MateBook X Pro,笔记本的参数包括重量、内存、硬盘和CPU,且同一型号的笔记本参数会存在差异。满足开闭原则的基础下,设计此场景。

    分析

    此场景主要的对象为两款笔记本,其中内部包含各种参数。因此要构建具体的实例,需要初始化时,对内部成员一一进行初始化。这些初始化代码一般会放在构造函数中,更糟糕的是可能会散落在各种使用代码中,不易被察觉。传统的方法或许暂时可以满足需求,但是维护起来令人抓狂,且违背开闭原则。

    概念

    此时可引进生成器模式,满足以上的设计需求。为避免在客户端使用时凌乱的使用构造函数,可将笔记本封装成类,内部提供必备参数的设置接口。提供统一的生成接口供用户使用以创建需要的实例。

    此处主要涉及到以下几个概念:

    生成器

    笔记本已经抽象为类了,只需要在使用时创建笔记本实例。但是这些代码放在散乱的主逻辑中是糟糕且难以维护的。因此可实现一个生成器专门用于做此类工作,其功能主要为设置固定的笔记本参数,返回该实例。

    不同的笔记本参数肯定是不同的,为符合开闭原则,设计为一类笔记本对应一个生成器实例。因此将生成器抽象为基类,派生出各个具体的生成器子类。

    指挥

    为便于生成器更加灵活的使用,例如各个参数的设置顺序、某些参数不需要等。可设计一个实例用于指挥生成器的使用。

    实现

    类图

    根据以上分析各类之间的关系,绘制出以下类图。

    生成器类图

    使用方法

    • 增加新产品笔记本

      若为同型号不同配置(低/中/高配)笔记本,可在Cdirector::BuildComputer()中做逻辑,见源码BuildComputer(ENOTEBOOK_TYPE notebookType)

      若非同型号笔记本,则需CComputer派生出新笔记本的生成类,交由CDirector实例生成具体的笔记本实例。

    • 删除不使用的新产品实例

      只需屏蔽CDirector的调用即可。

    源码

    #include <string>
    #include <iostream>
    
    using namespace std;
    
    typedef enum {
        ALLOCATION_MIN = 0,
        ALLOCATION_NORMAL,
        ALLOCATION_HIGH,
        ALLOCATION_MAX
    } ENOTEBOOK_TYPE;
    
    class CComputer
    {
    public:
        void   SetName(string value) { mName = value; }
        string   GetName() { return mName; }
        void   SetWeight(string value) { mWeight = value; }
        string GetWeight() { return mWeight; }
        void   SetMemary(string value) { mMemary = value; }
        string GetMemary() { return mMemary; }
        void   SetHardDisk(string value) { mHardDisk = value; }
        string GetHardDisk() { return mHardDisk; }
        void   SetCpu(string value) { mCpu = value; }
        string GetCpu() { return mCpu; }
    
    private:
        string mName;
        string mWeight;
        string mMemary;
        string mHardDisk;
        string mCpu;
    };
    
    class CComputerBuilder
    {
    public:
    
        virtual void BuildName() = 0;
        virtual void BuildWeight() = 0;
        virtual void BuildMemary() = 0;
        virtual void BuildHardisk() = 0;
        virtual void BuildHardiskHigh() = 0;
        virtual void BuildCpu() = 0;
        virtual CComputer* GetComputer() = 0;
    };
    
    class CThinkPadX13Builder : public CComputerBuilder
    {
    public:
    
        CThinkPadX13Builder()
        {
            mThinkPadX13 = new CComputer();
        }
    
        ~CThinkPadX13Builder()
        {
            delete mThinkPadX13;
        }
    
        void BuildName()
        {
            mThinkPadX13->SetName("ThinkPad X13");
        }
    
        void BuildWeight()
        {
            mThinkPadX13->SetWeight("1.3Kg");
        }
    
        void BuildMemary()
        {
            mThinkPadX13->SetMemary("32GB");
        }
    
        void BuildHardisk()
        {
            mThinkPadX13->SetHardDisk("512G");
        }
    
        void BuildHardiskHigh()
        {
            mThinkPadX13->SetHardDisk("1TB");
        }
    
        void BuildCpu()
        {
            mThinkPadX13->SetCpu("I5-10210U");
        }
    
        CComputer *GetComputer() {return mThinkPadX13;}
    
    private:
        CComputer* mThinkPadX13;
    };
    
    class CMateBookXProBuilder : public CComputerBuilder
    {
    public:
        CMateBookXProBuilder()
        {
            mMateBookXPro = new CComputer();
        }
    
        ~ CMateBookXProBuilder()
        {
            delete mMateBookXPro;
        }
    
        void BuildName()
        {
            mMateBookXPro->SetName("MateBook X Pro");
        }
    
        void BuildWeight()
        {
            mMateBookXPro->SetWeight("1.33KG");
        }
    
        void BuildMemary()
        {
            mMateBookXPro->SetMemary("16G");
        }
    
        void BuildHardisk()
        {
            mMateBookXPro->SetHardDisk("1TB");
        }
    
        void BuildHardiskHigh()
        {
            mMateBookXPro->SetHardDisk("2TB");
        }
    
        void BuildCpu()
        {
            mMateBookXPro->SetCpu("i7-1165G7");
        }
    
        CComputer* GetComputer() { return mMateBookXPro; }
    
    private:
        CComputer* mMateBookXPro;
    };
    
    class CDirector
    {
    public:
        CDirector(CComputerBuilder *pBuilder)
        {
            mBuilder = pBuilder;
        }
    
        void BuildComputer(ENOTEBOOK_TYPE notebookType)
        {
            mBuilder->BuildName();
            mBuilder->BuildWeight();
            mBuilder->BuildMemary();
            mBuilder->BuildCpu();
    
            if (notebookType == ALLOCATION_NORMAL)
            {
                mBuilder->BuildHardisk();
            } else if (notebookType == ALLOCATION_HIGH) {
                mBuilder->BuildHardiskHigh();
            } else {
                cout << "Error: No this type!" << endl;
            }
    
        }
    
    private:
        CComputerBuilder* mBuilder;
    };
    
    static void show_params(CComputer *pComputer)
    {
        cout << "---" << pComputer->GetName() << "---" << endl;
        cout << "Weight: " << pComputer->GetWeight() << endl;
        cout << "Memary: " << pComputer->GetMemary() << endl;
        cout << "Hard disk: " << pComputer->GetHardDisk() << endl;
        cout << "Cpu: " << pComputer->GetCpu() << endl;
        cout << endl;
    }
    
    int main(int argc, char *argv[])
    {
        CThinkPadX13Builder *theComputerBuilder1 = new CThinkPadX13Builder();
        CDirector *theDirector1 = new CDirector(theComputerBuilder1);
        theDirector1->BuildComputer(ALLOCATION_HIGH);
        CComputer *theComputer1 =  theComputerBuilder1->GetComputer();
        show_params(theComputer1);
        delete theDirector1;
        delete theComputerBuilder1;
    
        CMateBookXProBuilder *theComputerBuilder2 = new CMateBookXProBuilder();
        CDirector *theDirector2 = new CDirector(theComputerBuilder2);
        theDirector2->BuildComputer(ALLOCATION_HIGH);
        CComputer *theComputer2 =  theComputerBuilder2->GetComputer();
        show_params(theComputer2);
        delete theDirector2;
        delete theComputerBuilder2;
    
        return 0;
    }
    

    输出

    ---ThinkPad X13---
    Weight: 1.3Kg
    Memary: 32GB
    Hard disk: 1TB
    Cpu: I5-10210U
    
    ---MateBook X Pro---
    Weight: 1.33KG
    Memary: 16G
    Hard disk: 2TB
    Cpu: i7-1165G7
    

    总结

    在软件设计时,主函数的代码尽量减少实例初始化的动作,将初始化的行为尽量封装起来供主函数调用。主函数大多为业务逻辑,过多的代码会影响美观及维护。

    相关文章

      网友评论

          本文标题:S2. 生成器模式

          本文链接:https://www.haomeiwen.com/subject/azsloltx.html