2013-04-09 20 views
5

Basit bir dinamik FSM yazdım. Dynamic durum geçişleri ConcreteStateB'da gösterildiği gibi dinamik ve statik değil demektir.Dinamik durum makinesi için daha fazla .net yaklaşımı

namespace FSM_Example 
{ 
    using System; 

    class Program 
    { 
     static void Main() 
     { 
      var context = new Context(new ConcreteStateA()); 
      context.Run(); 
      Console.Read(); 
     } 
    } 

    abstract class State 
    { 
     public abstract void Execute(Context context); 
    } 

    class ConcreteStateA : State 
    { 
     public override void Execute(Context context) 
     { 
      context.State = new ConcreteStateB(); 
     } 
    } 

    class ConcreteStateB : State 
    { 
     public override void Execute(Context context) 
     { 
      Console.Write("Input state: "); 
      string input = Console.ReadLine(); 
      context.State = input == "e" ? null : new ConcreteStateA(); 
     } 
    } 

    class Context 
    { 
     private State _state; 

     public Context(State state) 
     { 
      State = state; 
     } 

     public State State 
     { 
      get { return _state; } 
      set 
      { 
       _state = value; 
       Console.WriteLine("State: " + _state.GetType().Name); 
      } 
     } 

     public void Run() 
     { 
      while (_state != null) 
      { 
       _state.Execute(this); 
      } 
     } 
    } 
} 

Bu GoF305 tarif edildiği gibi, bir durum makinesi uygular.

C# ve .net yeniyim beri: Daha iyi yaklaşımlar .net veya C# den daha spesifik özelliklerini kullanarak bu amaç var Arşivleme mı?

cevap

5

Outcoldman cevabı sayısız önemli seçenekler sunmanın ile hayata o

interface IState 
{ 
    Task HandleAsync(Context context); 
} 

class Context 
{ 
    // ... 

    public async Task RunAsync() 
    { 
     while (_state != null) 
     { 
      await _state.HandleAsync(this); 
     } 
    } 
} 
  • Benim bahis gibi bir şey için zaman uyumsuz kullanabilirsiniz.

    Şimdi, aşağıdaki kod desene göre uygun bir FSM olmadığını biliyoruz, ama çok basit uygulamalar için ekstra alt sınıfları bir sürü yazı önlemeye yardımcı olabilir. Bu sadece iş için doğru aracı belirleme meselesi. Bu seferki ağırlıklı Action<T> jenerik temsilci kullanımı etrafında odaklanır:

    public class Context 
    { 
        public Action<Context> State { get; internal set; } 
    
        public Context(Action<Context> state) 
        { 
         State = state; 
        } 
    
        public void Run() 
        { 
         while (State != null) 
         { 
          State(this); 
         } 
        } 
    } 
    

    Ve "devlet makinesini" bulunmaktadır:

    public static class SimpleStateMachine 
    { 
        public static void StateA(Context context) 
        { 
         context.State = StateB; 
        } 
        public static void StateB(Context context) 
        { 
         Console.Write("Input state: "); 
         var input = Console.ReadLine(); 
         context.State = input == "e" ? (Action<Context>)null : StateA; 
        } 
    } 
    

    Ve süreç başlıyor için kullandığınız ediyorum:

    var context = new Context(SimpleStateMachine.StateA); 
    context.Run(); 
    Console.Read(); 
    

    Ayrıca, gibi siz de Lambda ifadeleri kullanabilirsiniz ilgili olmayan devletler için:

    Action<Context> process = context => 
        { 
         //do something 
         context.State = nextContext => 
          { 
           //something else 
           nextContext.State = null; 
          }; 
        }; 
    
  • 2

    uygulayabilirsiniz bol yaklaşım vardır, ama çoğunlukla size ulaşmak için gereken görev bağlıdır.

    1. Soyut sınıf yerine arayüz kullanabilirsiniz. C# 'da birden fazla dersi miras edemezsiniz, bu yüzden bu seçeneği gerçekleştirmeden almamak her zaman iyidir.

      interface IState 
      { 
          void Handle(Context context); 
      } 
      
    2. kez Devlet deseni için taban arabirimleri/sınıfları yazmak ve her yerde kullanabilirsiniz, böylece eşdeğer ilaç kullanabilirsiniz:

      abstract class IState<T> 
      { 
          void Handle(T context); 
      } 
      
    3. Sonraki şeyler gizlemek veya don etmek istiyorsun bağlıdır saklanmak istemiyorum Örneğin, mülk sahibi için ayarlayıcıyı gizleyemezsiniz, hiç kimsenin dll'nizin dışında kullanamayacağından emin olmak için, bu özelliğin ayarını internal yapabilirsiniz.

    4. Sen Devlet Değişim, birileri zaten Rx