我是C#中状态模式实现的新手,你能否提供一些关于如何实现它的信息。
我正在使用状态模式在C#中重构状态机。目前我的状态机包含5个状态,只能通过状态前进或后退,即。从状态1开始,您需要进入状态2,3和4,最终到达状态5.
我能够继续前进
mainclass.State = new NextSate();
每次你想要前进时都会创建一个新状态,但是,一旦创建了所有状态和/或你想要后退,我就需要进入相同的状态,而不仅仅是新状态。我怎样才能做到这一点?有没有更好的方法来做到这一点?
答案 0 :(得分:10)
使用内部堆栈来维护以前的状态:
public class MyClass
{
private Stack<State> _states;
private State _currentState;
public void GoToNextState()
{
// If Not last state then
_states.Push(_currentState);
_currentState = new NextState();
}
public void GoToPrevState()
{
// if not the first state
_currentState = _states.Pop();
}
}
如果你想保持前进和后退状态,那么创建额外的堆栈:
public class MyClass
{
private readonly Stack<State> _nextStates = new Stack<State>();
private readonly Stack<State> _prevStates = new Stack<State>();
private State _currentState = new SampleState1();
public State CurrentState { get { return _currentState; } }
public void GoToNextState()
{
if (_currentState.NextState == null)
return;
_prevStates.Push(_currentState);
_currentState = _nextStates.Count > 0 ? _nextStates.Pop() : _currentState.NextState;
}
public void GoToPrevState()
{
// if not the first state
_nextStates.Push(_currentState);
_currentState = _prevStates.Pop();
}
}
答案 1 :(得分:10)
严格地说,如果你正在实现经典的GoF状态模式,那么State子类本身负责了解和执行状态转换。状态的持有者不负责管理转换,并且模式的大部分意图是将状态转换行为封装在State对象中,从而使客户端委托给它们。我引入了一个工厂,它确保每个State子类只有一个实例,以确保在状态中来回移动时重用相同的实例。
public abstract class State
{
protected StateFactory _factory;
protected IStateUser _context;
public State(StateFactory factory, IStateUser context)
{
_factory = factory;
_context = context;
}
protected void TransitionTo<T>(Func<T> creator) where T : State
{
State state = _factory.GetOrCreate<T>(creator);
_context.CurrentState = state;
}
public abstract void MoveNext();
public abstract void MovePrevious();
}
public class State1 : State
{
public State1(StateFactory factory, IStateUser context)
: base(factory, context)
{
}
public override void MoveNext()
{
TransitionTo<State2>(() => new State2(_factory, _context));
}
public override void MovePrevious()
{
throw new InvalidOperationException();
}
}
public class State2 : State
{
public State2(StateFactory factory, IStateUser context)
: base(factory, context)
{
}
public override void MoveNext()
{
TransitionTo<State3>(() => new State3(_factory, _context)); //State 3 is omitted for brevity
}
public override void MovePrevious()
{
TransitionTo<State1>(() => new State1(_factory, _context));
}
}
public interface IStateUser
{
State CurrentState { get; set; }
}
public class Client : IStateUser
{
public Client()
{
var factory = new StateFactory();
var first = new State1(factory, this);
CurrentState = factory.GetOrCreate<State1>(() => first);
}
public void MethodThatCausesTransitionToNextState()
{
CurrentState.MoveNext();
}
public void MethodThatCausesTransitionToPreviousState()
{
CurrentState.MovePrevious();
}
public State CurrentState
{
get;
set;
}
}
public class StateFactory
{
private Dictionary<string, State> _states = new Dictionary<string, State>();
public State GetOrCreate<T>(Func<T> creator) where T : State
{
string typeName = typeof(T).FullName;
if (_states.ContainsKey(typeName))
return _states[typeName];
T state = creator();
_states.Add(typeName, state);
return state;
}
}
答案 2 :(得分:0)
你有某种形式的州长吗?如果是这样,那个可以保存状态实例。通过将状态转换知识与状态本身分离,您可以让经理决定转换。经理将检查请求转换的状态:它确定它是&#34;步骤1&#34;状态,并返回(或创建)&#34;状态2&#34;状态。