我目前正在尝试实施一个大约有10个州的应用程序。与传统的状态模式不同,传统的状态模式只有一个链接指向一个状态的不同状态,我希望它更像是一个有向图,其中一个状态可以有多个边到不同的状态。
示例:我有状态1-10(顶点)。 - 是边缘。这些可能是可能的状态转换。
1-2,1-3,1-6 2-3,2-9 3-5 4-3 5-2,5-3,5-4 6-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() ;
}
......
我可以想到反射和一堆switch语句来解决这个问题,但我想我也可以应用状态模式或者在这里提出一个更优雅的解决方案,但我绝对卡住了。
任何帮助或指导将不胜感激!
答案 0 :(得分:0)
由于涉及状态转换图,因此需要维持邻接关系并定义转换标准。此标准可以对所有节点通用(例如,从一个节点到另一个节点的过渡由过渡成本决定),也可以针对每个节点进行自定义(例如,在某些节点上,过渡基于成本发生,而其他过渡则基于节点发生)类型)。
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;
};