//2.策略模式 //ver1 //現金收費抽象類 class CashSuper { public: CashSuper(){} ~CashSuper(){} public: virtual double acceptCash(double money) { return money; } }; //正常收費類 class CashNormal : public CashSuper { public: CashNormal(){} ~CashNormal(){} public: virtual double acceptCash(double money) { return money; } }; //打折收費類 class CashRebate : public CashSuper { private: double _moneyRebate; public: CashRebate(double moneyRebate) { _moneyRebate = moneyRebate; } virtual double acceptCash(double money) { return money * _moneyRebate; } }; //返利收費類 class CashReturn : public CashSuper { private: double _moneyCondition; double _moneyReturn; public: CashReturn(double moneyCondition, double moneyReturn) { _moneyCondition = moneyCondition; _moneyReturn = moneyReturn; } virtual double acceptCash(double money) { double result = money; if (money >= _moneyCondition) { money = money - floor(money/_moneyCondition) * _moneyReturn; //floor 向下取整; ceil 向上取整 } return money; } }; enum eCashType { eNormal = 1, eRebate = 2, eReturn = 3 }; //現金收費工廠類 class CashFactory { public: static CashSuper CreateCashAccept(eCashType eType) { CashSuper * cs = NULL; switch(eType) { case eNormal: cs = new CashNormal(); break; case eRebate: cs = new CashRebate(0.8); break; case eReturn: cs =new CashReturn(300, 100); break; default: break; } return *cs; } }; void main1() { double total = 0.0; CashSuper csuper = CashFactory::CreateCashAccept(eRebate); total = csuper.acceptCash(350); //這裏不方便在於,無法控制多少折; 參數無法傳入; //解決:這裏的處理是在定義枚舉時分別定義,好比定八折 eRebate8 ,5折 eRebate5; 增長對應 case 語句; //缺點: 工廠包含了全部的收費方式,每增長一種或者修改一種收費方式,都須要更改工廠內容; }
策略模式: 定義算法家族,分別封裝起來,讓它們之間能夠互相替換,此模式讓算法的變化,不會影響到算法的客戶.
算法
//2.策略模式 //抽象算法類 class Strategy { public: virtual void AlgorithmInterface() = 0; }; //具體算法A class ConcreteStrategyA : public Strategy { public: virtual void AlgorithmInterface() { //算法A } }; //具體算法B class ConcreteStrategyB : public Strategy { public: virtual void AlgorithmInterface() { //算法B } }; //上下文; 用於管理 Strategy class Context { private: Strategy * _strategy; public: Context(Strategy * strategy) { _strategy = strategy; } //上下文接口 void ContextInterface() { _strategy->AlgorithmInterface(); } }; void main21() { Context *pContext = new Context(new ConcreteStrategyA()); pContext->ContextInterface(); pContext = new Context(new ConcreteStrategyB()); pContext->ContextInterface(); } //2.策略模式 //ver2 //現金收費抽象類 class CashSuper { public: CashSuper(){} ~CashSuper(){} public: virtual double acceptCash(double money) { return money; } }; //正常收費類 class CashNormal : public CashSuper { public: CashNormal(){} ~CashNormal(){} public: virtual double acceptCash(double money) { return money; } }; //打折收費類 class CashRebate : public CashSuper { private: double _moneyRebate; public: CashRebate(double moneyRebate) { _moneyRebate = moneyRebate; } virtual double acceptCash(double money) { return money * _moneyRebate; } }; //返利收費類 class CashReturn : public CashSuper { private: double _moneyCondition; double _moneyReturn; public: CashReturn(double moneyCondition, double moneyReturn) { _moneyCondition = moneyCondition; _moneyReturn = moneyReturn; } virtual double acceptCash(double money) { double result = money; if (money >= _moneyCondition) { money = money - floor(money/_moneyCondition) * _moneyReturn; //floor 向下取整; ceil 向上取整 } return money; } }; enum eCashType { eNormal = 1, eRebate = 2, eReturn = 3 }; class CashContext { private: CashSuper _csuper; public: CashContext(CashSuper cs) { _csuper = cs; } double GetResult(double money) { return _csuper.acceptCash(money); } }; //客戶端調用 void main22() { CashContext *pcc = NULL; CashSuper *pcs = NULL; eCashType eType = eRebate; switch(eType) { case eNormal: pcs = new CashNormal(); *pcc = CashContext(*pcs); break; case eRebate: pcs = new CashRebate(0.8); *pcc = CashContext(*pcs); case eReturn: pcs = new CashReturn(300, 100); *pcc = CashContext(*pcs); default: break; } double money = 350; double result = pcc->GetResult(money); //缺點: 判斷過程放在了客戶端,暴露了太多的細節; }
//3.策略模式 //ver3 //跟前面的ver2一致,只修改main和CashContext類; class CashContext { private: CashSuper * pcs; public: CashContext(eCashType eType) { switch(eType) { case eNormal: pcs = new CashNormal(); break; case eRebate: pcs = new CashRebate(0.8); break; case eReturn: pcs = new CashReturn(300, 100); break; default: break; } } double GetResult(double money) { return pcs->acceptCash(money); } }; void main31() { CashContext *pcs = new CashContext(eRebate); double total = pcs->GetResult(350); //對比ver2,簡單工廠模式客戶端調用須要知道 CashSuper 和 CashFactory 類; //ver3, 簡單工廠+策略模式,客戶端只須要知道 CashContext 類: }
//策略模式的Strategy類爲Context定義了一系列的可供重用的算法或行爲。繼承有助於取出這些算法中的公共功能。 //策略模式的優勢是簡化了單元測試,由於每一個算法都有本身的類,能夠經過本身的接口單獨測試。
//另外一種更好的模式多是 反射模式。 單元測試