設計模式 -- 策略模式 -- c++實現

注:本文主要代碼基於大話設計模式裏的C#代碼(第2章)。

 

UML圖:

 

策略模式的實現:

將所要用的所有算法抽象出一個接口(所以每個算法要用類實現)

使用一個策略上下文類,封裝一個算法接口的指針,並提供一個函數給外部調用具體算法。

外部用具體算法類的指針來創建策略上下文類。


下面代碼是一個商場收費系統的抽象,將收費的算法(普通,打折,返利)抽象成cCashSuper接口

在策略上下文類cCashContext中使用工廠模式,可以將具體算法的調用與調用者解耦。


代碼如下:

/*****************************************************
* 模式名:策略模式
* 時間:2010.6.3
*                                       -by gouki04
*****************************************************/

#pragma once

//////////////////////////////////////////////////////////////////////////
class cCashContext;         // (策略上下文類,封裝了一個策略接口的指針)
class cCashContext_Factory; // (策略上下文類與簡單工廠模式結合)
class cCashSuper;           // 收費類接口(策略接口,定義所有算法的公共接口)
class cCashNormal;          // 普通收費類(基本策略類)
class cCashRebate;          // 打折收費類(基本策略類)
class cCashReturn;          // 返利收費類(基本策略類)
//////////////////////////////////////////////////////////////////////////

// 收費類接口(策略接口,定義所有算法的公共接口)
class cCashSuper
{
public:
    // 收費方法
    // 參數:money爲原收費
    // 返回:應收費
    virtual double AcceptCash(double money) = 0;
};

// 普通收費類(基本策略類)
class cCashNormal : public cCashSuper
{
public:
    double AcceptCash(double money) { return money; }
};

// 打折收費類(基本策略類)
class cCashRebate : public cCashSuper
{
private:
    double m_moneyRebate; // 折扣率

public:
    cCashRebate(double rebate = 1.0) : m_moneyRebate(rebate) {}
    double AcceptCash(double money) { return money * m_moneyRebate; }
};

// 返利收費類(基本策略類)
// 例:滿300返100
class cCashReturn : public cCashSuper
{
private:
    double m_moneyCondition; // 返還條件的金錢數
    double m_moneyReturn;  // 返還的金錢數

public:
    cCashReturn(double condition = 0.0, double _return = 0.0) : m_moneyCondition(condition), m_moneyReturn(_return) {}
    double AcceptCash(double money)
    {
        if (money > m_moneyCondition)
            money -= static_cast<int>(money / m_moneyCondition) * m_moneyReturn;
        return money;
    }
};

// (策略上下文類,封裝了一個策略接口的指針)
class cCashContext
{
private:
    cCashSuper * m_pCashSuper;

public:
    cCashContext(cCashSuper* cs) : m_pCashSuper(cs) {}
    virtual ~cCashContext() { /* 這裏沒有必要析構m_pCashSuper,因爲它是外部引入,應該由外部負責析構 */ }

    // 調用具體的收費算法
    double AcceptCash(double money) { return m_pCashSuper->AcceptCash(money); }
};

// 策略上下文類與簡單工廠模式結合
// 將具體的選擇算法的過程封裝起來
class cCashContext_Factory
{
private:
    cCashSuper * m_pCashSuper;

public:
    // 此處的構造函數體應該放在cpp文件中,這裏爲了方便閱讀而改爲內聯函數
    // 像switch這樣的語句不應該使用內聯
    cCashContext_Factory(int type = 0)
    {
        switch (type) {
        case 0:
            m_pCashSuper = new cCashNormal();
            break;
        case 1:
            m_pCashSuper = new cCashRebate(0.8);
            break;
        case 2:
            m_pCashSuper = new cCashReturn(300, 100);
            break;
        default:
            throw type;
        }
    }
    virtual ~cCashContext_Factory() { if (m_pCashSuper) delete m_pCashSuper; }

    // 調用具體的收費算法
    double AcceptCash(double money) { return m_pCashSuper->AcceptCash(money); }
};

// 測試的main函數 
//int main()
//{
//    using namespace std;
//
//    cCashContext* pContext = NULL;
//    cCashSuper* pCashSuper = NULL;
//    try {
//        int type = 0;
//        cout << "0 --> 普通收費" << endl << "1 --> 打8折" << endl << "2 --> 滿300返100" << endl << "請選擇收費方式:";
//        cin >> type;
//
//        switch (type) {
//        case 0:
//            pCashSuper = new cCashNormal();
//            break;
//        case 1:
//            pCashSuper = new cCashRebate(0.8);
//            break;
//        case 2:
//            pCashSuper = new cCashReturn(300, 100);
//            break;
//        default:
//            throw type;
//        }
//        pContext = new cCashContext(pCashSuper);
//
//        cout << endl << "總費用爲:";
//        double totalPrice = 0;
//        cin >> totalPrice;
//
//        cout << endl << "應收費爲:" << pContext->AcceptCash(totalPrice) << endl;
//    }
//    catch (int type) {
//        cout << "沒有" << type << "這種收費方式。" << endl;
//    }
//    catch (...) {
//        cout << "輸入錯誤" << endl;
//    }
//
//    if (pContext)
//        delete pContext;
//
//    if (pCashSuper)
//        delete pCashSuper;
//
//    return 0;
//}

// 使用策略模式+工廠模式的main函數
//int main()
//{
//    using namespace std;
//
//    cCashContext_Factory* pContext = NULL;
//
//    try {
//        int type = 0;
//        cout << "0 --> 普通收費" << endl << "1 --> 打8折" << endl << "2 --> 滿300返100" << endl << "請選擇收費方式:";
//        cin >> type;
//        pContext = new cCashContext_Factory(type);
//
//        cout << endl << "總費用爲:";
//        double totalPrice = 0;
//        cin >> totalPrice;
//
//        cout << endl << "應收費爲:" << pContext->AcceptCash(totalPrice) << endl;
//    }
//    catch (int type) {
//        cout << "沒有" << type << "這種收費方式。" << endl;
//    }
//    catch (...) {
//        cout << "輸入錯誤" << endl;
//    }
//
//    if (pContext)
//        delete pContext;
//
//    return 0;
//}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章