Singletonパターンのメリットは
- 振る舞いを簡単に交換することが出来る。
- 振る舞いを動的に交換することが出来る。
まずは次のクラス図をご覧ください
ちゃんとクリックして拡大して見てくださいね。
このクラス図で重要なのは
- MonsterStrategyクラス
つぎにソースを見てみましょう、用意するのは次のファイルです。
- main.cpp
- Monster.h
- Monster.cpp
- MonsterStrategy.h
- MonsterStrategy.cpp
- MonsterStrategyFreedom.h
- MonsterStrategyFreedom.cpp
- MonsterStrategyGangan.h
- MonsterStrategyGangan.cpp
- #ifndef _MONSTER_H_
- #define _MONSTER_H_
- #include "MonsterStrategy.h"
- class Monster
- {
- //----------------------------------
- // constant
- //----------------------------------
- #define STRATEGY_MAX_NUM 8
- //----------------------------------
- // field
- //----------------------------------
- private:
- MonsterStrategy* m_strategyDictionary[STRATEGY_MAX_NUM]; // ①
- MonsterStrategy::Type m_currentStrategyType; // ②
- //----------------------------------
- // property
- //----------------------------------
- public:
- const MonsterStrategy::Type getCurrentStrategyType();
- Monster& setCurrentStrategyType(const MonsterStrategy::Type _type);
- private:
- MonsterStrategy** getStrategyDictionary();
- const bool addStrategy(const MonsterStrategy::Type _type);
- //----------------------------------
- // mothod
- //----------------------------------
- public:
- // constructor
- Monster();
- // destructor
- ~Monster();
- // initialize
- const bool init();
- // move
- Monster& move(); // ③
- private:
- // operator(=)
- Monster& operator=(const Monster& _monster);
- };
- #endif
②現在の行動アルゴリズムです。
③Monsterに行動指示を出します。
次にMonster.cppです。
- #include "Monster.h"
- #include "MonsterStrategyFreedom.h"
- #include "MonsterStrategyGangan.h"
- #include <stdio.h>
- //-----------------------------------
- // property
- //-----------------------------------
- const MonsterStrategy::Type Monster::getCurrentStrategyType()
- {
- return this->m_currentStrategyType;
- }
- Monster& Monster::setCurrentStrategyType(const MonsterStrategy::Type _type)
- {
- printf("strategy %d -> %d\n", this->getCurrentStrategyType(), _type);
- this->m_currentStrategyType = _type;
- return *this;
- }
- MonsterStrategy** Monster::getStrategyDictionary()
- {
- return this->m_strategyDictionary;
- }
- const bool Monster::addStrategy(const MonsterStrategy::Type _type)
- {
- if (STRATEGY_MAX_NUM <= _type) {
- throw "error strategy max num";
- }
- MonsterStrategy** strategyDictionary = this->getStrategyDictionary();
- if (strategyDictionary[_type] != NULL) {
- // already exist
- return false;
- }
- switch (_type) {
- case MonsterStrategy::ST_FREEDOM:
- strategyDictionary[_type] = new MonsterStrategyFreedom();
- break;
- case MonsterStrategy::ST_GANGAN:
- strategyDictionary[_type] = new MonsterStrategyGangan();
- break;
- default:
- throw "invalid type";
- break;
- }
- return true;
- }
- //-----------------------------------
- // method
- //-----------------------------------
- // constructor
- Monster::Monster() :
- m_currentStrategyType(MonsterStrategy::ST_FREEDOM)
- {
- // do nothing...
- }
- // destructor
- Monster::~Monster()
- {
- MonsterStrategy** strategyDictionary = this->getStrategyDictionary();
- for (int i = 0; i < STRATEGY_MAX_NUM; i++) {
- delete strategyDictionary[i];
- }
- }
- // initialize
- const bool Monster::init()
- {
- MonsterStrategy** strategyDictionary = this->getStrategyDictionary();
- for (int i = 0; i < STRATEGY_MAX_NUM; i++) {
- strategyDictionary[i] = NULL;
- }
- const MonsterStrategy::Type strategyTypeArray[] = {
- MonsterStrategy::ST_FREEDOM,
- MonsterStrategy::ST_GANGAN,
- };
- const int size = sizeof(strategyTypeArray) / sizeof(MonsterStrategy::Type); // ①
- for (int i = 0; i < size; i++) {
- this->addStrategy(strategyTypeArray[i]);
- }
- return true;
- }
- // move
- Monster& Monster::move()
- {
- MonsterStrategy** strategyDictionary = this->getStrategyDictionary();
- strategyDictionary[this->getCurrentStrategyType()]->move(*this);
- return *this;
- }
- </stdio.h>
次にMonsterStrategy.hです。
- #ifndef _MONSTER_STRATEGY_H_
- #define _MONSTER_STRATEGY_H_
- class Monster;
- class MonsterStrategy
- {
- public:
- //----------------------------------
- // constant
- //----------------------------------
- enum Type {
- ST_FREEDOM = 0, // 自由
- ST_GANGAN, // がんがん行こうぜ
- }; // ①
- //----------------------------------
- // mothod
- //----------------------------------
- public:
- // constructor
- MonsterStrategy();
- // destructor
- virtual ~MonsterStrategy();
- // move
- virtual void move(Monster& _monster) = 0; // ②
- private:
- // operator(=)
- MonsterStrategy& operator=(const MonsterStrategy& _monsterStrategy);
- };
- #endif
②Monsterの行動アルゴリズムが記述されているメソッドです。タイプ毎にアルゴリズムは違うので純粋仮想関数にしています。
次にMonsterStrategy.cppです。
- #include "MonsterStrategy.h"
- #include <stdio.h>
- //----------------------------------
- // mothod
- //----------------------------------
- // constructor
- MonsterStrategy::MonsterStrategy()
- {
- // do nothing...
- }
- // destructor
- MonsterStrategy::~MonsterStrategy()
- {
- // do nothing...
- }
- </stdio.h>
次に
MonsterStrategyFreedom.h
MonsterStrategyFreedom.cpp
MonsterStrategyGangan.h
MonsterStrategyGangan.cpp
をまとめて記述します。
- #ifndef _MONSTER_STRATEGY_FREEDOM_H_
- #define _MONSTER_STRATEGY_FREEDOM_H_
- #include "MonsterStrategy.h"
- class Monster;
- class MonsterStrategyFreedom : public MonsterStrategy // ①
- {
- public:
- //----------------------------------
- // mothod
- //----------------------------------
- public:
- // constructor
- MonsterStrategyFreedom();
- // destructor
- ~MonsterStrategyFreedom();
- // move
- void move(Monster& _monster); // ②
- private:
- // operator(=)
- MonsterStrategyFreedom& operator=(const MonsterStrategyFreedom& _monsterStrategyFreedom);
- };
- #endif
- #include "MonsterStrategyFreedom.h"
- #include "MonsterStrategy.h"
- #include "Monster.h"
- #include <stdio.h>
- //----------------------------------
- // mothod
- //----------------------------------
- // constructor
- MonsterStrategyFreedom::MonsterStrategyFreedom()
- {
- // do nothing...
- }
- // destructor
- MonsterStrategyFreedom::~MonsterStrategyFreedom()
- {
- // do nothing...
- }
- // move
- void MonsterStrategyFreedom::move(Monster& _monster)
- {
- printf("freedom\n");
- }</stdio.h>
- #ifndef _MONSTER_STRATEGY_GANGAN_H_
- #define _MONSTER_STRATEGY_GANGAN_H_
- #include "MonsterStrategy.h"
- class Monster;
- class MonsterStrategyGangan : public MonsterStrategy // ①
- {
- public:
- //----------------------------------
- // mothod
- //----------------------------------
- public:
- // constructor
- MonsterStrategyGangan();
- // destructor
- ~MonsterStrategyGangan();
- // move
- void move(Monster& _monster); // ②
- private:
- // operator(=)
- MonsterStrategyGangan& operator=(const MonsterStrategyGangan& _monsterStrategyGangan);
- };
- #endif
- #include "MonsterStrategyGangan.h"
- #include "MonsterStrategy.h"
- #include "Monster.h"
- #include <stdio.h>
- //----------------------------------
- // mothod
- //----------------------------------
- // constructor
- MonsterStrategyGangan::MonsterStrategyGangan()
- {
- // do nothing...
- }
- // destructor
- MonsterStrategyGangan::~MonsterStrategyGangan()
- {
- // do nothing...
- }
- // move
- void MonsterStrategyGangan::move(Monster& _monster)
- {
- printf("inochi\n");
- }
- </stdio.h>
②オーバーライドしたmove()メソッドです。
最後にmain.cppです。
- #include "Monster.h"
- #include <stdio.h>
- void main(void)
- {
- Monster monster; // モンスター生成
- monster.init(); // 初期化
- monster.move(); // move
- monster.setCurrentStrategyType(MonsterStrategy::ST_GANGAN); // 戦略変更
- monster.move(); // move
- printf("hit any key...");
- while(getchar() == EOF){}
- }
- </stdio.h>
以上でStrategyパターンの説明は終わりです。クラス数は少し多いですがそんなに難しいパターンではないはずです。
ソースコードはコピペで動かせるハズですので是非試してみてください。
0 件のコメント:
コメントを投稿