简体   繁体   English

具有先前状态的状态模式 C#

[英]State Pattern C# with previous states

I am new to the state pattern implementation in C#, could you provide some info on how you implement it.我是 C# 中状态模式实现的新手,您能否提供一些有关如何实现它的信息。

I am refactoring a state machine in C# using the state pattern.我正在使用状态模式在 C# 中重构状态机。 Currently my state machine contains 5 states and it is only possible to go forward or backward througout the states,ie from state 1 you need to go to state 2, 3 and 4 to finally arrive to state 5.目前我的状态机包含 5 个状态,并且只能在这些状态中前进或后退,即从状态 1 到状态 2、3 和 4 才能最终到达状态 5。在此处输入图片说明

I am able to go forward just doing我能够前进只是做

       mainclass.State = new NextSate();

which creates a new state every time you want to go forward, however, once all of them have been created and/or you want to go backward I would need to go to the same states, not just a new one.每次您想要前进时都会创建一个新状态,但是,一旦所有状态都已创建和/或您想要后退,我将需要进入相同的状态,而不仅仅是一个新状态。 How can I do that?我怎样才能做到这一点? Is there any better way to do it simple?有没有更好的方法来简单地做到这一点?

Use internal stack to maintain the previous states:使用内部堆栈来维护之前的状态:

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();
   }
}

if you want to maintain forward and backward states then create additional stack:如果要保持前进和后退状态,则创建额外的堆栈:

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();
    }
}

Strictly speaking, if you're implementing the classic GoF State pattern then the State subclasses themselves are responsible for knowing about and performing the State transitions.严格来说,如果您正在实现经典的 GoF 状态模式,那么状态子类本身负责了解和执行状态转换。 The holder of the State isn't responsible for managing the transitions and a large part of the intent of the pattern is to encapsulate the state transition behaviour in the State objects and thus for the client to delegate to them. State 的持有者不负责管理转换,该模式的大部分意图是将状态转换行为封装在 State 对象中,从而让客户端委托给它们。 I've introduced a Factory that ensures that there is only ever a single instance of each State subclass to ensure that the same instance is reused when moving back and forth through the states.我引入了一个工厂,它确保每个 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;
    }
}

Do you have a state manager of some kind?你有某种状态经理吗? If so, that one could hold the state instances.如果是这样,那个人可以持有状态实例。 By decoupling the state transition knowledge from the states themselves, you let the manager decide on the transition.通过将状态转换知识与状态本身解耦,您可以让经理决定转换。 The manager will inspect the state that requested the transition: it determines it is the "step 1" state, and returns (or creates) the "state 2" state.管理器将检查请求转换的状态:它确定它是“步骤 1”状态,并返回(或创建)“状态 2”状态。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM