1. 程式人生 > >設計模式—模板方法的C++實現

設計模式—模板方法的C++實現

構圖 操作 clust urn out 數據統計 pac 技術 soft

這是Bwar在2009年寫的設計模式C++實現,代碼均可編譯可運行,一直存在自己的電腦裏,曾經在團隊技術分享中分享過,現搬到線上來。

1. 模板方法簡述

1.1 目的

定義一個操作中的算法骨架,而將一些步驟延遲到子類中。TemplateMethod使得子類可以不改變一個算法的結構即可重定義該算法的某些特定步驟。

1.2 適用性

(1) 一次性實現一個算法的不變部分,並將可變的信鴿網i留給子類來實現。

(2) 各子類中公共的行為應被提取出來並幾種到一個公共父類中以避免代碼重復。

(3) 控制子類的擴展。

2. 模板方法結構圖

技術分享圖片

  • AbstractClass:定義抽象的原語操作,具體的子類將重定義它們以實現一個算法的各步驟;實現一個模板方法,定義一個算法的股價。
  • ConcreteClass:實現原語操作以完成算法中與特定子類相關的步驟。

3. 模板方法C++實現示例

用模板方法實現遊戲的數據統計框架。遊戲往往有很多服,稱之為大區,MMO遊戲中也稱之為World。遊戲的數據統計會有很多數據指標,所有數據指標都既需要全局的統計,又需要各大區的分開統計,這些數據指標的統計邏輯統計方法又是完全一樣的。我們用模板方法定義一個適用於所有指標(活躍、流失、留存、付費等)的統計框架,具體統計邏輯留給子類實現。這樣的一個遊戲框架在2009年到2013年在行業第一的遊戲公司用在一百多款各類型遊戲數據統計上,當然,模板方法只是這個遊戲數據統計框架最基礎的一部分,一個通用的遊戲數據統計框架並沒有那麽簡單。

Run()為模板方法,Run()方法內固定依次調用ClusterInit()、Stat()、ClusterStat()。ClusterInit()完成統計初始化,Stat()完成各大區的分區統計,ClusterStat()完成所有大區結果去重統計。整個統計框架實現多線程調度,但具體實現統計邏輯的子類並無須關註線程調度,甚至完全不懂線程的開發人員也能使用該統計框架開發出多線程統計程序。Run()模板方法確保了ClusterInit()只會在第一個進入統計邏輯的線程執行且只執行一次(此時,其他線程處於等待ClusterInit()完成的阻塞狀態);Stat()方法在每個線程中同時開始執行;ClusterStat()只在最後一個完成Stat()的線程執行且只執行一次。統計邏輯開發者只需專註於這三個方法的具體實現,其他都交給框架完成,而框架則是通過者三個方法將骨架定義好,確保所有統計都按固定流程走。

技術分享圖片

代碼實現:

AbstractClass.h:

#ifndef ABSTRACTCLASS_H_
#define ABSTRACTCLASS_H_

#include <iostream>

using namespace std;

class CAbstractClass
{
public:
    CAbstractClass();
    virtual ~CAbstractClass();

    int Run();

protected:
    virtual int Stat() = 0;

    virtual int ClusterInit()
    {
        return 0;
    }

    virtual int ClusterStat()
    {
        return 0;
    }

    int GetWorldId()
    {
        cout << "1" << endl;
        return 1;
    }
};

#endif /* ABSTRACTCLASS_H_ */

AbstractClass.cpp:

#include "AbstractClass.h"

CAbstractClass::CAbstractClass()
{
    // TODO Auto-generated constructor stub
    cout << "abstract class construct" << endl;
}

CAbstractClass::~CAbstractClass()
{
    // TODO Auto-generated destructor stub
    cout << "abstract class destruct" << endl;
}

int CAbstractClass::Run()
{
    ClusterInit();
    Stat();
    ClusterStat();
    return 0;
}

ConcreteClass.h:

#ifndef CONCRETECLASS_H_
#define CONCRETECLASS_H_

#include "AbstractClass.h"

class CConcreteClass : public CAbstractClass
{
public:
    CConcreteClass();
    virtual ~CConcreteClass();

    /*
    virtual int Run()
    {
        Stat();
        ClusterInit();
        ClusterStat();
    }
    */

protected:
    virtual int Stat();

    virtual int ClusterInit()
    {
        cout << "CConcreteClass ClusterInit()" << endl;
    }

    virtual int ClusterStat()
    {
        cout << "CConcreteClass ClusterStat()" << endl;
    }

};

#endif /* CONCRETECLASS_H_ */

ConcreteClass.cpp:

#include "ConcreteClass.h"

CConcreteClass::CConcreteClass()
{
    // TODO Auto-generated constructor stub
    cout << "concrete class construct" << endl;
}

CConcreteClass::~CConcreteClass()
{
    // TODO Auto-generated destructor stub
    cout << "concrete class destruct" << endl;
}

int CConcreteClass::Stat()
{
    cout << "ConcreteClass::Stat()" << endl;
}

TemplateMethodMain.cpp:

#include <iostream>
#include "AbstractClass.h"
#include "ConcreteClass.h"

using namespace std;

int main()
{
    CAbstractClass* pStat = new CConcreteClass();
    //CConcreteClass* pStat = new CConcreteClass();

    pStat->Run();

    delete pStat;

    return 0;
}

模板方法在高性能的C++異步通信框架Nebula中也有廣泛應用,Nebula框架的Actor中的Cmd、Step、Session都使用了模板方法。

技術分享圖片

設計模式—模板方法的C++實現