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 遷移を認識して実行する責任があります。State の所有者は遷移を管理する責任を負わず、パターンの意図の大部分は、状態遷移の動作を State オブジェクトにカプセル化し、クライアントがそれらに委譲することです。各 State サブクラスのインスタンスが 1 つだけであることを保証する Factory を導入して、状態間を行き来するときに同じインスタンスが再利用されるようにしました。

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 に答える