最近、休止後にC ++開発に戻り、StateDesignPatternの実装について質問があります。GoFの本とまったく同じように、バニラパターンを使用しています。
私の問題は、ステートマシン自体が組み込みシステムの一部として使用されるハードウェアに基づいているため、設計が修正されて変更できないことです。これにより、2つの状態(特に)の間に循環依存が発生し、これを解決しようとしています。簡略化されたコードは次のとおりです(通常どおりヘッダーを使用してこれを解決しようとしましたが、それでも問題が発生しました。このコードスニペットではヘッダーを省略しています)。
#include <iostream>
#include <memory>
using namespace std;
class Context
{
public:
friend class State;
Context() { }
private:
State* m_state;
};
class State
{
public:
State() { }
virtual void Trigger1() = 0;
virtual void Trigger2() = 0;
};
class LLT : public State
{
public:
LLT() { }
void Trigger1() { new DH(); }
void Trigger2() { new DL(); }
};
class ALL : public State
{
public:
ALL() { }
void Trigger1() { new LLT(); }
void Trigger2() { new DH(); }
};
// DL needs to 'know' about DH.
class DL : public State
{
public:
DL() { }
void Trigger1() { new ALL(); }
void Trigger2() { new DH(); }
};
class HLT : public State
{
public:
HLT() { }
void Trigger1() { new DH(); }
void Trigger2() { new DL(); }
};
class AHL : public State
{
public:
AHL() { }
void Trigger1() { new DH(); }
void Trigger2() { new HLT(); }
};
// DH needs to 'know' about DL.
class DH : public State
{
public:
DH () { }
void Trigger1() { new AHL(); }
void Trigger2() { new DL(); }
};
int main()
{
auto_ptr<LLT> llt (new LLT);
auto_ptr<ALL> all (new ALL);
auto_ptr<DL> dl (new DL);
auto_ptr<HLT> hlt (new HLT);
auto_ptr<AHL> ahl (new AHL);
auto_ptr<DH> dh (new DH);
return 0;
}
問題は、基本的に、状態パターンでは、次の状態のコンストラクターを呼び出すContextクラスのChangeStateメソッドを呼び出すことによって状態遷移が行われることです。
循環依存のため、「問題」状態の両方のコンストラクターを事前に定義することができないため、コンストラクターを呼び出すことができません。
私はこの記事を見て、理想的な解決策のように思われたテンプレートメソッドを調べましたが、コンパイルされず、テンプレートに関する私の知識はかなり限られています...
私が持っていたもう1つのアイデアは、多重継承を介してヘルパークラスをサブクラス化された状態に導入し、基本クラスのコンストラクターを指定して、状態サブクラスのコンストラクターを参照できるかどうかを確認することです。しかし、それはかなり野心的だったと思います...
最後に、ファクトリメソッドデザインパターンを直接実装することが、問題全体を解決するための最良の方法でしょうか?