設計模式實現(二)---策略模式、策略模式與簡單工廠模式結合使用
阿新 • • 發佈:2019-01-09
策略模式(Strategy): 它定義了演算法家族,分別封裝起來,讓它們之間可以互相替換,此模式讓演算法的變化,不會影響到使用演算法的使用者。
策略模式大致實現方法
#include <stdio.h> //抽象演算法類 class Strategy { public: virtual void AlgorithmInterface() = 0; }; //具體演算法A class ConcreteStragtegyA : public Strategy { public: void AlgorithmInterface() { printf("方法 A 實現 \n"); } }; //具體演算法B class ConcreteStragtegyB : public Strategy { public: void AlgorithmInterface() { printf("方法 B 實現 \n"); } }; //具體演算法C class ConcreteStragtegyC : public Strategy { public: void AlgorithmInterface() { printf("方法 C 實現 \n"); } }; //上下文 class Context { public: //初始化的時候傳入具體策略的引用 Context(Strategy &str) : strategy(str){} //引用必須在引數初始化列表中初始化 public: //根據具體的策略呼叫具體的方法 void ContextInterface() { strategy.AlgorithmInterface(); } private: Strategy &strategy; //此處可以用引用,也可以用指標。 }; int main() { //Context *context = new Context(*(new ConcreteStragtegyA())); //context->ContextInterface(); //delete context; //context = new Context(*(new ConcreteStragtegyB())); //context->ContextInterface(); //delete context; //context = new Context(*(new ConcreteStragtegyC())); //context->ContextInterface(); //delete context; ConcreteStragtegyA stragtegyA; Context context(stragtegyA); context.ContextInterface(); ConcreteStragtegyB stragtegyB; Context context1(stragtegyB); context1.ContextInterface(); ConcreteStragtegyC stragtegyC; Context context2(stragtegyC); context2.ContextInterface(); return 1; }
利用單純策略模式解決商城自費調整的問題:
策略類:
上下文類//cash.h class CashSuper { public: virtual double acceptCash(double money) = 0; }; class CashNormal : public CashSuper { public: double acceptCash(double money) { return money; } }; class CashRebate : public CashSuper { public: CashRebate(double rebate){moneyRebate = rebate;} public: double acceptCash(double money) { return money*moneyRebate; } private: double moneyRebate; }; class CashReturn : public CashSuper { public: CashReturn(double condition,double returnback) { moneyCondition = condition; moneyReturn = returnback; } public: double acceptCash(double money) { if(money > moneyCondition) { return money - ((int)money / (int)moneyCondition)*moneyReturn; } else return money; } private: double moneyCondition; double moneyReturn; };
class CashContext
{
public:
CashContext(CashSuper *type)
{
this->cashType = type;
}
~CashContext()
{
if(cashType != NULL)
delete cashType;
cashType = NULL;
}
double getResult(double money)
{
return cashType->acceptCash(money);
}
private:
CashSuper *cashType;
};
客戶端方法:
#include <stdio.h> #include "context.h" //單純的策略模式 //裡面還是需要知道cashType類和CashContext類,兩個類。並沒有做到降低耦合度的要求, //而且還需要再客戶端判斷到底是建立哪一個cashType類。 //所以最好將策略模式與工廠模式結合使用,可以降低耦合度,並且客戶端不用判斷要建立哪個物件。 int main() { CashContext *test1 = new CashContext(new CashNormal()); printf("%f \n",test1->getResult(500)); delete test1; test1 = new CashContext(new CashRebate(0.6)); printf("%f \n",test1->getResult(500)); delete test1; test1 = new CashContext(new CashReturn(300,100)); printf("%f \n",test1->getResult(500)); delete test1; return 1; }
策略模式與簡單工廠模式結合
策略類與上面的相同。
上下文類:
//與工廠模式結合的策略模式
class CashContextWithFactory
{
public:
CashContextWithFactory(char *in)
{
if(strcmp(in,"正常收費")==0)
{
cashType = new CashNormal();
}
else if(strcmp(in,"滿300減100")==0)
{
cashType = new CashReturn(300,100);
}
else if(strcmp(in,"打6折")==0)
{
cashType = new CashRebate(0.6);
}
}
~CashContextWithFactory()
{
if(cashType != NULL)
delete cashType;
cashType = NULL;
}
double getResult(double money)
{
return cashType->acceptCash(money);
}
private:
CashSuper *cashType;
};
客戶端方法:
//與工廠模式結合的設計模式
//客戶端部需要判斷建立哪個物件,只需要輸入對應的條件就可以
//客戶端中只需要知道CashContextWithFactory類就可以,使得客戶端與具體收費演算法徹底分離,不需要再客戶端中判斷呼叫哪個演算法的物件
//策略模式的另一個特點是每一個演算法都有自己單獨的類,可以利用演算法介面進行單獨測試
//修改某個演算法只需要修改其類就可以,不需要動其他的類
//不過,在CashContextWithFactory裡面還是利用了switch來判斷建立哪種演算法,後面將學習反射模式,可以解決該問題。
int main()
{
CashContextWithFactory *test1 = new CashContextWithFactory("正常收費");
printf("%f \n",test1->getResult(500));
delete test1;
test1 = new CashContextWithFactory("滿300減100");
printf("%f \n",test1->getResult(500));
delete test1;
test1 = new CashContextWithFactory("打6折");
printf("%f \n",test1->getResult(500));
delete test1;
return 1;
}