我目前正在尝试实现一个大约有10个州的应用程序。不像传统的状态模式,从一个状态到另一个状态只有一个链接,我希望它更像一个有向图,一个状态可以有多个边到不同的状态。
示例:我有状态1-10(顶点)。-是边。这些可以是可能的状态转换。
1- 2,1 - 3,1 -62 - 3、2 - 93 - 54 - 35-2, 5-3, 5-46- 3,6 -4,6- 7,6 -9…等等
每个状态都是类,每个边(-)是方法。例如:
Class State1 {
public void goToState2() ;
public void goToState3() ;
public void goToState6() ;
}
Class State2 {
public void goToState3() ;
public void goToState9() ;
}
…
我可以想到反射和一堆开关语句来解决这个问题,但我认为我也可以应用状态模式或提出一个更优雅的解决方案,但我绝对卡住了。
任何帮助或指导将不胜感激!
由于涉及到状态转移图,因此需要保持邻接关系并定义转移标准。该标准可以对所有节点通用(例如,从一个节点到另一个节点的转换由转换成本决定),也可以为每个节点定制(例如,在某些节点上的转换基于成本,而在其他节点上的转换基于节点类型)。
class ExecutionParameters;
class IState;
using SPState = std::shared_ptr<IState>;
using SPStates = std::list<SPState>;
class _declspec(novtable) IState
{
public:
virtual void Execute(Context& context, const ExecutionParameters& params) = 0;
virtual SPStates GetAdjacentStates() const noexcept = 0;
};
class _declspec(novtable) ITransitionCriteria
{
public:
virtual SPState ComputeNextState() const = 0;
};
class CostBasedTransition : public ITransitionCriteria
{
public:
SPState ComputeNextState() const override
{
// Find min transition cost adjacent node
}
};
using SPTransitionCriteria = std::shared_ptr<ITransitionCriteria>;
class StateNode : public IState
{
public:
StateNode(int id, SPTransitionCriteria spTransitionCriteria) :m_id(id), m_spTransitionCriteria(spTransitionCriteria)
{}
StateNode(int id) :StateNode(id, nullptr)//Choose default transition criteria//)
{}
void Execute(Context& context, const ExecutionParameters& params) override
{
// Perform action
// Update context state
context.SetState(m_spTransitionCriteria->GetNextState());
}
SPStates GetAdjacentStates() const noexcept
{
return m_spAdjacentStates;
}
void AddAjacentState(SPState spState)
{
}
void RemoveAjacentState(int stateId)
{
}
private:
int m_id;
SPStates m_spAdjacentStates;
SPTransitionCriteria m_spTransitionCriteria;
};
class Context
{
public:
void Execute(const ExecutionParameters& params)
{
m_spState->Execute(*this, params);
}
void SetState(SPState& spState)
{
m_spState = spState;
}
private:
SPState m_spState;
};