策略模式:定義了算法家族,分別封裝起來,讓它們之間可以互相替換,此模式讓算法的變化,不會影響到使用算法的客戶。
組成:
-
抽象策略角色Strategy:策略類,定義了所有支持的算法的公共接口
-
具體策略角色ConcreteStrategyA : Strategy :繼承自Strategy,封裝了具體的算法或行爲,可能有很多。
-
環境角色或者上下文角色,持有一個對Strategy對象的引用,給客戶端調用的。
應用場景:eg商場促銷;遊戲中不同狀態下人物的技能
-
多個類只在表現行爲不同,在運行時候動態選擇不同的行爲
-
不同的情況下使用不同的策略(算法),策略很可能在未來用其他方式實現
-
對客戶端隱藏算法具體細節,彼此完全獨立
優點:
1. 避免代碼的重複:把公有的代碼放在父類裏
2. 繼承使得動態改變算法或邏輯變得可能
3. 避免多重條件轉移語句
缺點:
客戶端必須知道所有的策略類
每個具體策略都對應一個類,這時可以考慮下共享的辦法
一個例子:商場打折
結構圖如下
#include <iostream>
#include <cmath>
#include <map>
using namespace std;
//抽象算法類 : 現金收費
class CashSuper {
public:
virtual double acceptCash(double money) = 0;
};
//具體算法A:正常收費
class CashNormal : public CashSuper {
public:
double acceptCash(double money)
{
return money;
}
};
//具體算法B:打折收費
class CashRebate : public CashSuper {
public:
CashRebate(double _moneyRebate)
: moneyRebat(_moneyRebate)
{
}
double acceptCash(double money)
{
return money * moneyRebat;
}
private:
double moneyRebat;
};
//具體算法A:返利收費,滿?反?
class CashReturn : public CashSuper {
public:
CashReturn(double _moneyCondition = 0.0, double _moneyReturn = 0.0)
: moneyCondition(_moneyCondition), moneyReturn(_moneyReturn)
{
}
double acceptCash(double money)
{
double result = money;
if(money > moneyCondition)
{
result = money - floor(money/moneyCondition) * moneyReturn;
}
return result;
}
private:
double moneyCondition;
double moneyReturn;
};
//上下文Context,與簡單工廠模式結合後的產物
class CashContext {
private:
CashSuper *cs = NULL;
public:
CashContext(string type)
{
if(type == "正常收費") {
cs = new CashNormal();
} else if(type == "滿300返100") {
cs = new CashReturn(300, 100);
} else if(type == "打8折") {
cs = new CashRebate(0.8);
}
}
double getResult(double money)
{
return cs->acceptCash(money);
}
};
int main() {
double total = 0.0;
CashContext *csuper = new CashContext("正常收費");
total = total + csuper->getResult(5.0 * 4); //單價5.0 * 4個
cout << "單項價格:" << csuper->getResult(5.0 * 4) << endl; //20
delete csuper;
csuper = new CashContext("打8折");
total = total + csuper->getResult(4.0 * 5);
cout << "單項價格:" << csuper->getResult(4.0 * 5) << endl; //16
delete csuper;
csuper = new CashContext("滿300返100");
total = total + csuper->getResult(220.0 * 3);
cout << "單項價格:" << csuper->getResult(220.0 * 3) << endl; //460
delete csuper;
cout << "最終的應該付款:" << total << endl; //496
return 0;
}