Resolving a Forward Declaration Issue Involving a State Machine in C++
- by hypersonicninja
I've recently returned to C++ development after a hiatus, and have a question regarding
implementation of the State Design Pattern. I'm using the vanilla pattern, exactly as
per the GoF book.
My problem is that the state machine itself is based on some hardware used as part of
an embedded system - so the design is fixed and can't be changed. This results in a
circular dependency between two of the states (in particular), and I'm trying to
resolve this. Here's the simplified code (note that I tried to resolve this by using
headers as usual but still had problems - I've omitted them in this code snippet):
#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;
}
The problem is basically that in the State Pattern, state transitions are made by
invoking the the ChangeState method in the Context class, which invokes the
constructor of the next state.
Because of the circular dependency, I can't invoke the constructor because it's
not possible to pre-define both of the constructors of the 'problem' states.
I had a look at this article, and the template method which seemed to be the ideal solution - but it doesn't compile and my knowledge of templates is a rather limited...
The other idea I had is to try and introduce a Helper class to the subclassed states,
via multiple inheritance, to see if it's possible to specify the base class's constructor
and have a reference to the state subclasse's constructor. But I think that was rather
ambitious...
Finally, would a direct implmentation of the Factory Method Design Pattern be the best way
to resolve the entire problem?