8

我是 C# 中状态模式实现的新手,您能否提供一些有关如何实现它的信息。

我正在使用状态模式在 C# 中重构状态机。目前我的状态机包含 5 个状态,只能通过状态前进或后退,即从状态 1 到状态 2、3 和 4 最终到达状态 5。在此处输入图像描述

我能够继续前进

       mainclass.State = new NextSate();

每次您想前进时都会创建一个新状态,但是,一旦所有这些都已创建和/或您想后退,我将需要进入相同的状态,而不仅仅是一个新状态。我怎样才能做到这一点?有没有更好的方法让它变得简单?

4

3 回答 3

11

使用内部堆栈来维护以前的状态:

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();
    }
}
于 2011-10-24T10:15:47.197 回答
11

严格来说,如果您正在实现经典的 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;
    }
}
于 2011-10-24T13:43:53.597 回答
0

你有某种状态经理吗?如果是这样,那一个可以保存状态实例。通过将状态转换知识与状态本身分离,您可以让经理决定转换。管理器将检查请求转换的状态:它确定它是“步骤 1”状态,并返回(或创建)“状态 2”状态。

于 2011-10-24T10:16:13.813 回答