注:本文主要代碼基於大話設計模式裏的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;
//}