日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

設(shè)計(jì)模式介紹之六:工廠模式(factory)的巧妙

系統(tǒng) 1691 0

本文展示了實(shí)際項(xiàng)目中使用到的一個(gè)工廠模式實(shí)現(xiàn),在向系統(tǒng)中添加新類(lèi)型時(shí),只需要在新類(lèi)型的實(shí)現(xiàn)文件這一處做改動(dòng),將新增類(lèi)型對(duì)應(yīng)用程序代碼的干擾降到了最低。

這個(gè)工廠實(shí)現(xiàn)的基本思想是:繼承自同一個(gè)接口的新類(lèi)型,通過(guò)一個(gè)函數(shù)來(lái)創(chuàng)建其對(duì)象,利用C++ 中類(lèi)的構(gòu)造函數(shù)會(huì)被自動(dòng)調(diào)用這一特性,在新類(lèi)型的實(shí)現(xiàn)文件中定義一個(gè)靜態(tài)的(輔助)類(lèi)對(duì)象,在該輔助類(lèi)的構(gòu)造函數(shù)中,向工廠單例注冊(cè)新類(lèi)型的創(chuàng)建函數(shù)。

先看下代碼,然后我們一一來(lái)解釋。下面是命令接口 CommandObject 的頭文件內(nèi)容:

    class CommandObject
{
public:
    CommandObject(){}
    virtual ~CommandObject(){}

    virtual void execute() = 0;
};
  

CommandObject 是一個(gè)純虛類(lèi),作為公共的接口。

我在正式的系統(tǒng)中使用命令模式,封裝特定的操作,傳遞命令對(duì)象給一些 UI 元素,如 button 等,在 UI 元素被鼠標(biāo)或按鍵觸發(fā)時(shí),會(huì)調(diào)用關(guān)聯(lián)的 CommandObject 來(lái)執(zhí)行特定的命令。有關(guān)命令模式,參考文章《 設(shè)計(jì)模式介紹之三:命令模式(command) 》。

下面是命令對(duì)象工廠類(lèi)的頭文件:

    #ifndef COMMANDOBJECTFACTORY_H
#define COMMANDOBJECTFACTORY_H

#include "commandObject.h"

typedef CommandObject * (*LPFNCREATE)();

class  CommandObjectFactory
{
    CommandObjectFactory(const CommandObjectFactory &);
    CommandObjectFactory & operator=(const CommandObjectFactory &);
    CommandObjectFactory();

public:
    ~CommandObjectFactory();

    static CommandObjectFactory * instance();
    CommandObject * commandObject(const char * szKeyword);

    void regist(const char * szKeyword, LPFNCREATE lpfnCreate);

private:
    const char ** m_keywords;
    LPFNCREATE * m_functions;
    int m_iCount;
    int m_iCursor;
};


#define EXPORT_COMMAND_CREATOR(KEYWORD, COMMANDCLASS) \
    CommandObject * _command_object_creator_##KEYWORD() {\
        return new COMMANDCLASS;\
    }\
    class Static##KEYWORD##PluginInstance{ \
    public: \
        Static##KEYWORD##PluginInstance(){ \
            CommandObjectFactory::instance()->regist(#KEYWORD, _command_object_creator_##KEYWORD);\
        }\
    };\
    static Static##KEYWORD##PluginInstance static##KEYWORD##Instance

#endif // COMMANDOBJECTFACTORY_H

  

在這個(gè)頭文件中,定義了 CommandObjectFactory 這個(gè)工廠類(lèi)。首先它是一個(gè)單例( singleton ),這是通常的做法,工廠類(lèi)作為單例實(shí)現(xiàn)。關(guān)于單例,請(qǐng)參考文章《 設(shè)計(jì)模式介紹之二:?jiǎn)卫J?Singleton) 》。

CommandObjectFactory 定義了用于創(chuàng)建對(duì)象的工廠方法 commandObject ,它接受一個(gè)字符串作為關(guān)鍵字,內(nèi)部根據(jù)這個(gè)關(guān)鍵字來(lái)創(chuàng)建命令對(duì)象。還定義了一個(gè)方法 regist ,用來(lái)向工廠內(nèi)注冊(cè)命令對(duì)象的創(chuàng)建函數(shù),主要是被后面定義的輔助宏EXPORT_COMMAND_CREATOR 使用,自動(dòng)進(jìn)行創(chuàng)建函數(shù)的注冊(cè)。

宏EXPORT_COMMAND_CREATOR 有兩個(gè)參數(shù),一個(gè)是與具體命令對(duì)象實(shí)現(xiàn)類(lèi)一一對(duì)應(yīng)的關(guān)鍵字 KEYWORD,一個(gè)是命令對(duì)象類(lèi)類(lèi)名 COMMANDCLASS 。這個(gè)宏非常關(guān)鍵,正是它幫助我們完成創(chuàng)建函數(shù)的注冊(cè),同時(shí)使得我們把新增類(lèi)型的代碼改動(dòng)限制在新類(lèi)型的實(shí)現(xiàn)文件中,對(duì)已有代碼沒(méi)有任何影響。

宏EXPORT_COMMAND_CREATOR展開(kāi)后又分為幾部分:輔助類(lèi)聲明、作用域?yàn)槲募娜朱o態(tài)輔助類(lèi)實(shí)例、輔助類(lèi)構(gòu)造函數(shù)調(diào)用 CommandObjectFactory::regist() 注冊(cè)創(chuàng)建函數(shù)。它的使用也非常簡(jiǎn)單,我們會(huì)在后面提到。

下面是 CommandObjectFactory 的實(shí)現(xiàn):

    #include "commandObjectFactory.h"
#include <iostream>
#include <string.h>
#include <malloc.h>

using namespace std;

#define INITIALISE_SIZE    32
#define INCREMENT_SIZE     8
static CommandObjectFactory * s_instance = 0;
CommandObjectFactory::CommandObjectFactory()
    : m_keywords(0)
    , m_functions(0)
    , m_iCount(0)
    , m_iCursor(0)
{
}

CommandObjectFactory::~CommandObjectFactory()
{
}

CommandObjectFactory * CommandObjectFactory::instance()
{
    if(!s_instance)
    {
        s_instance = new CommandObjectFactory;
        cout << "CommandObjectFactory initialised" << endl;
    }

    return s_instance;
}


void CommandObjectFactory::regist(const char * szKeyword, LPFNCREATE lpfnCreate)
{
    if(!szKeyword || !lpfnCreate) return;

    //repeat check
    for(int i = 0; i < m_iCursor; ++i)
    {
        if(!strcmp(m_keywords[i], szKeyword))
            return ;
    }

    if(!m_functions)
    {
        m_functions = (LPFNCREATE*)calloc(INITIALISE_SIZE, sizeof(LPFNCREATE));
        m_keywords = (const char**)calloc(INITIALISE_SIZE, sizeof(char*));
        m_iCount = INITIALISE_SIZE;
        m_iCursor = 0;
    }
    else if( m_iCursor == m_iCount )
    {
        m_iCount += INCREMENT_SIZE;
        m_functions = (LPFNCREATE*)realloc( m_functions, m_iCount * sizeof(LPFNCREATE) );
        m_keywords = (const char**)realloc( m_keywords, m_iCount * sizeof(char*));
    }

    m_keywords[m_iCursor] = (const char *)strdup(szKeyword);
    m_functions[m_iCursor] = lpfnCreate;

    m_iCursor++;
    cout << "register create function for - " << szKeyword << endl;
}

CommandObject * CommandObjectFactory::commandObject(const char * szKeyword)
{
    for(int i = 0; i < m_iCursor; ++i)
    {
        if(!strcmp(m_keywords[i], szKeyword))
        {
            return m_functions[i]();
        }
    }
    cout << "no create function for - " << szKeyword << endl;
    return 0;
}

  

實(shí)現(xiàn)比較簡(jiǎn)單,我們?cè)?CommandObjectFactory 內(nèi)部維護(hù)了兩個(gè)數(shù)組,分別存貯關(guān)鍵字和命令對(duì)象創(chuàng)建函數(shù),兩者一一對(duì)應(yīng), regist() 函數(shù)維護(hù)創(chuàng)建函數(shù)的注冊(cè)和內(nèi)部數(shù)組的動(dòng)態(tài)增長(zhǎng)。 commandObject() 函數(shù)則根據(jù)傳入的關(guān)鍵字 szKeyword ,在內(nèi)部的數(shù)組中做字符串比較,關(guān)鍵字匹配后定位對(duì)應(yīng)的創(chuàng)建函數(shù)來(lái)創(chuàng)建命令對(duì)象。

下面看看具體命令對(duì)象類(lèi)的實(shí)現(xiàn)和自動(dòng)注冊(cè)宏EXPORT_COMMAND_CREATOR 的使用。代碼:

    class ShutdownCommand : public CommandObject
{
public:
    void execute()
    {
        cout << endl << "ShutdownCommand::execute" << endl;
    }
};

EXPORT_COMMAND_CREATOR(shutdown, ShutdownCommand);


class RebootCommand : public CommandObject
{
public:
    void execute()
    {
        cout << endl << "RebootCommand::execute" << endl;
    }
};
EXPORT_COMMAND_CREATOR(reboot, RebootCommand);

  

一切都很直觀,不必多說(shuō)了。

下面是 main() 函數(shù),看看怎么使用命令對(duì)象工廠來(lái)創(chuàng)建想要的命令對(duì)象:

    int main()
{
    CommandObject * cmd = CommandObjectFactory::instance()->commandObject("shutdown");
    cmd->execute();
    return 0;
}
  

非常簡(jiǎn)單,不必要解釋了。下面是程序執(zhí)行的結(jié)果:

設(shè)計(jì)模式介紹之六:工廠模式(factory)的巧妙實(shí)現(xiàn)

好啦,到現(xiàn)在為止,一個(gè)簡(jiǎn)單好用的簡(jiǎn)單工廠模式實(shí)現(xiàn)介紹完畢,我特意做了簡(jiǎn)化,以便能更好的理解實(shí)現(xiàn)的思路,在實(shí)際的項(xiàng)目中,稍微復(fù)雜了一些。

回顧:


設(shè)計(jì)模式介紹之六:工廠模式(factory)的巧妙實(shí)現(xiàn)


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 乌海市| 乐安县| 加查县| 永顺县| 大厂| 清原| 怀安县| 南皮县| 张家口市| 历史| 集安市| 秦安县| 奉节县| 桦川县| 津南区| 射洪县| 泰来县| 特克斯县| 上林县| 柯坪县| 永州市| 中西区| 门头沟区| 滨海县| 老河口市| 普兰县| 苏尼特右旗| 白银市| 洪泽县| 茶陵县| 浙江省| 鄂伦春自治旗| 永吉县| 布尔津县| 余庆县| 安仁县| 清河县| 新龙县| 上蔡县| 广昌县| 金沙县|