設計模式:可復用面向對象軟件的基礎 書中對 Strategy 模式的定義如下:
定義了一系列的算法,把它們一個個封裝起來,並且使它們可相互替換。本模式使得算法可獨立於它的用戶而變化。
案例:設計一個商場收銀軟件,營業員根據客戶所購買商品的單價和數量,向客戶收費。商場有許多促銷的策略,打折,滿300減100等。。。
1. 如果采用之前將的工廠模式,可以采用如下的方式編寫:
// Last Update:2014-03-17 21:05:53 /** * @file cash.h * @brief Strategy Pattern * @author shoulinjun@126.com * @version 0.1.00 * @date 2014-03-17 */ #ifndef CASH_H #define CASH_H #include#include #include #include // base class // define interface class CashSuper { public: virtual ~CashSuper() {} virtual double acceptCash(double money) = 0; }; class CashNormal : public CashSuper { public: double acceptCash(double money){ return money; } }; class CashRebate : public CashSuper{ public: CashRebate(std::string moneyRate = "0.0"){ std::stringstream s(moneyRate); s >> this->moneyRate_; } double acceptCash(double money){ return money * moneyRate_; } private: double moneyRate_; }; class CashReturn : public CashSuper{ public: CashReturn(std::string moneyCondition, std::string moneyReturn){ std::stringstream s(moneyCondition); s >> this->moneyCondition_; std::stringstream s2(moneyReturn); s2 >> this->moneyReturn_; } double acceptCash(double money){ if(money >= moneyCondition_){ money -= std::floor(money / moneyCondition_) * moneyReturn_; } return money; } private: double moneyCondition_, moneyReturn_; }; // factory class class CashFactory{ public: static CashSuper* createCashSuper(std::string type) { CashSuper *pCashSuper(NULL); if(type == "正常收費"){ pCashSuper = new CashNormal(); } else if(type == "滿300減100"){ pCashSuper = new CashReturn("300", "100"); } else if(type == "打8折"){ pCashSuper = new CashRebate("0.8"); } else{ return NULL; } return pCashSuper; } }; #endif /*CASH_H*/ #include "cash.h" #include #include "boost/shared_ptr.hpp" using namespace std; int main(void) { boost::shared_ptr pCashSuper(CashFactory::createCashSuper("正常收費")); cout << pCashSuper->acceptCash(300) << endl; pCashSuper = boost::shared_ptr (CashFactory::createCashSuper("打8折")); cout << pCashSuper->acceptCash(300) << endl; pCashSuper = boost::shared_ptr (CashFactory::createCashSuper("滿300減100")); cout << pCashSuper->acceptCash(300) << endl; return 0; }
2. Strategy 模式
策略模式可以減少各種算法類與使用算法類之間的耦合;
簡化單元測試,因為每個算法都有自己的類,可以通過自己的接口進行單元測試。// base class
// define interface
class CashSuper
{
public:
virtual ~CashSuper() {}
virtual double acceptCash(double money) = 0;
};
class CashNormal : public CashSuper
{
public:
double acceptCash(double money){
return money;
}
};
class CashRebate : public CashSuper{
public:
CashRebate(std::string moneyRate = "0.0"){
std::stringstream s(moneyRate);
s >> this->moneyRate_;
}
double acceptCash(double money){
return money * moneyRate_;
}
private:
double moneyRate_;
};
class CashReturn : public CashSuper{
public:
CashReturn(std::string moneyCondition, std::string moneyReturn){
std::stringstream s(moneyCondition);
s >> this->moneyCondition_;
std::stringstream s2(moneyReturn);
s2 >> this->moneyReturn_;
}
double acceptCash(double money){
if(money >= moneyCondition_){
money -= std::floor(money / moneyCondition_) * moneyReturn_;
}
return money;
}
private:
double moneyCondition_, moneyReturn_;
};
class CashContext{
public:
CashContext(std::string type): pCashSuper_(NULL){
if(type == "正常收費"){
pCashSuper_ = new CashNormal;
}
else if(type == "滿300減100"){
pCashSuper_ = new CashReturn("300", "100");
}
else if(type == "打8折"){
pCashSuper_ = new CashRebate("0.8");
}
// else
}
~CashContext(){
if(pCashSuper_)
delete pCashSuper_;
}
double GetResult(double money){
assert(pCashSuper_ != NULL);
return pCashSuper_->acceptCash(money);
}
private:
CashSuper *pCashSuper_;
// copy not allowed
CashContext(const CashContext&);
CashContext& operator=(const CashContext&);
};
// 客戶端使用如下:
CashContext csuper("滿300減100");
cout << csuper.GetResult(300) << endl;
參考資料:
1. 大話設計模式
2. 設計模式:可復用面向對象軟件的基礎