日曜日, 2月 23, 2014

今更デザインパターン - Strategy

Strategyパターンは,既存システムの機能拡張,とりわけ別のプロトコルへの適応といった場合や,汎用的なケースに対応できるシステムの開発において使われると思われる.

例えば最初はデータをすべてNFSディスクに保存する仕様だったのが,次に,代わりにデータをHDFSに保存するように仕様変更する,といった具合である.

このような場合に解放/閉鎖原則に遵守しつつシステム変更を行う定石の一つとしてStrategyパターンを適用することであろう.

Strategyパターンはアルゴリズム・ロジックをカプセル化し,呼び出しクラスからはそれらが可換であることを満たす必要がある.

以下の例は日本語変換ロジックとドイツ語変換ロジックをカプセル化し,呼び出し元において変換ロジックをドイツ語から日本語に取り換えている.

#include <iostream>
#include <string>
#include <stdexcept>
using namespace std;

class TransAlg {
public:
 virtual string translate(const string str) = 0;
};

class GermanTrans:public TransAlg {
public:
 virtual string translate(const string str) {
  if( str == "welcome" )
   return "willkommen";
  else
   return "weiss nicht";
 }
};

class JapanTrans:public TransAlg {
public:
 virtual string translate(const string str) {
  if( str == "welcome" )
   return "yokoso";
  else
   return "wakannai";
 }
};

class Translator {

private:
 TransAlg* m_alg;
 bool isReady;
public:
 Translator():isReady(false) {}
 string translate(const string str);
 void SetAlg(TransAlg* alg) { m_alg = alg; isReady = true; }
};

string Translator::translate(const string str ) {

 if( isReady ) {
  return m_alg->translate(str);
 }
 else
  throw logic_error("algorithm not set") ;
}


int main() {

 TransAlg* alg;
 alg = new GermanTrans();
 Translator trans;

 try {
  trans.SetAlg(alg);
  cout << "translating to German:" << trans.translate("welcome") << endl;
  delete alg;
  alg = new JapanTrans();
  trans.SetAlg(alg);
  cout << "translating to Japanese:" << trans.translate("welcome") << endl;
  delete alg;
 }catch(exception& e) {
  cerr << "err:" << e.what() << endl;
 }

}

0 件のコメント: