У меня есть машина состояния C ++, реализованная с использованием шаблона проектирования State. Каждое состояние реализовано как вложенный класс друга контекстного класса.
class Context {
public:
/* The Context class' user calls process1() to get it to perform an action */
void process1();
private:
class IState;
void switchState( IState *newState );
class IState {
virtual void doProcess( Context &context ) = 0;
};
class StateA : public Context::IState {
void doProcess( Context &context );
};
friend class StateA;
class StateB : public Context::IState {
void doProcess( Context &context );
};
friend class StateB;
.
.
.
class StateJ : public Context::IState {
void doProcess( Context &context );
};
friend class StateJ;
};
В настоящее время успешная итерация конечного автомата выполняется от Context::StateA
до Context::StateJ
при вызове Context::process1()
, но некоторые из состояний содержат внутреннюю логику, чтобы определить, следует ли вернуться к более раннему состоянию. Таким образом, типичное исполнение будет выглядеть так:
StateA
StateB
StateC
StateD
StateE
StateC
StateD
StateE
StateF
StateG
StateH
StateI
StateJ
Внутренняя логика для определения следующего состояния в настоящее время реализуется самим соответствующим состоянием путем сохранения данных в объекте контекста. Теперь мне нужно добавить опцию Context::process2()
, которая значительно отличается в порядке выполнения состояний. Конечно, это можно сделать с помощью флагов, которые установлены в объекте контекста, но мне было интересно, есть ли лучший способ реализовать это; возможно, даже используйте этот метод для перезаписи обработки переключателей состояний в Context::process2()
.
Шаблон проектирования Visitor может помочь, но я не уверен, предназначен ли он для реализации конечных автоматов. При использовании Visitor process1()
может содержать всю логику для порядка выполнения состояний, а затем просто вызывать каждое состояние в этом порядке. Точно так же process2()
будет обрабатывать всю свою собственную логику.
EDIT:
Тем из вас, кто ответил, что я должен создать отдельный конечный автомат, я стараюсь избегать этого потому, что код состояний, используемый вторым конечным автоматом, идентичен коду первого; отличается только прогрессия.
Второй конечный автомат пройдет через следующие переходы состояний:
StateA
StateB
StateC
StateJ
Поэтому я пытаюсь удалить дублирующийся код.