Design Patterns----Strategyモード


設計モード:多重化対象ソフトウェアの基礎書におけるStrategyモードの定義は以下の通りである.
一連のアルゴリズムを定義し,それらを一つ一つカプセル化し,互いに置き換えることができるようにした.このモードは、アルゴリズムをそのユーザから独立して変化させることができる.
ケース:デパートのレジソフトを設計し、営業員はお客様が購入した商品の単価と数量に基づいて、お客様に料金を徴収します.デパートには販促の策略がたくさんあります.割引して、300いっぱいで100を減らすなど..
ポリシーモードは、様々なアルゴリズムクラスと使用アルゴリズムクラスとの結合を低減することができる.
各アルゴリズムには独自のクラスがあるため、ユニットテストを独自のインタフェースで行うことができます.
注意:次のコードでは、CashContextのスマートポインタクラスを使用してベースクラスのポインタを保存します.
#include <string>
#include <iostream>
#include <sstream>
#include <cmath>
#include <cassert>

/* abstract 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_;
};

/* handler class
 * smart pointer
 */
class CashContext{
public:
    CashContext(std::string type)
    : pCashSuper_(NULL), use(new std::size_t(1))
    {
        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
    }

    // copy control
    CashContext(const CashContext &rhs)
    : pCashSuper_(rhs.pCashSuper_), use(rhs.use)
    {
      ++ *use;
    }
    // deal with self-assignment
    CashContext& operator=(const CashContext &rhs){
      ++ *(rhs.use);
      if(-- *use == 0){ 
        delete pCashSuper_;
        delete use;
      }
      pCashSuper_ = rhs.pCashSuper_;
      use = rhs.use;
      return *this;
    }

    ~CashContext(){
      if(-- *use == 0){
        delete pCashSuper_;
        delete use;
      }
    }
    
    double GetResult(double money){
        assert(pCashSuper_ != NULL); 
        return pCashSuper_->acceptCash(money);
    }
private:
    CashSuper *pCashSuper_;
    std::size_t *use;
};

参考資料:
1.大話設計モード
2.設計モード:多重化可能なオブジェクト向けソフトウェアの基礎