2012-02-09 67 views
1

我想實現一個命令模式。我有以下幾點:實現命令模式和多態性

public class State 
{ 
    public int Number { get; set; } 

    public void Execute(IAction action) 
    { 
     if (action.IsValid(this)) 
      action.Apply(this); 
    }    
} 

public interface IAction 
{ 
    bool IsValid(State state); 
    void Apply(State state); 
}  

public class ActionSet5IfZero : IAction 
{ 

    public bool IsValid(State state) 
    { 
     if (state.Number == 0) 
      return true; 
     else 
      return false; 
    } 

    public void Apply(State state) 
    { 
     state.Number = 5; 
    } 
} 

而且程序:

static void Main(string[] args) 
{ 
    State s = new State(); 
    s.Execute(new ActionSet5IfZero()); 
} 

按預期工作。我的問題開始,當我想延長State類:

public class ExtendedState : State 
{ 
    public int Number2 { get; set; } 
} 

現在的動作必須在ExtendedState應用更改。所以我想我會創建具有采取ExtendedState作爲參數的兩個附加的功能擴展行動:

public class ExtendedActionSet5IfZero : IAction 
{ 

    public bool IsValid(State state) 
    { 
     throw new NotImplementedException(); 
    } 

    public void Apply(State state) 
    { 
     throw new NotImplementedException(); 
    } 

    public bool IsValid(ExtendedState state) 
    { 
     if (state.Number == 0 && state.Number2 == 0) 
      return true; 
     else 
      return false; 
    } 

    public void Apply(ExtendedState state) 
    { 
     state.Number = 5; 
     state.Number2 = 5; 
    } 
} 

這事我已經不喜歡,因爲實現接口的功能變得多餘。此外,我需要在我的ExtendedState中創建一個新的Execute函數,它使用新類型而不是IAction(否則未實現的函數會被調用)。

我相信它可以用一個很好的OO方式完成。你能幫我嗎?其目的是創建一個可擴展的State類和IAction接口(可能甚至是通用的,我不知道),所以我可以擴展State,但仍然是通用功能,無需額外編碼。

回答

0

你可以使用泛型:

interface IAction<TState> where TState: State 
{ 
    bool IsValid(TState state); 
    void Apply(TState state); 
} 
+1

我以前試過這個。問題是當我擴展State類並嘗試重用Execute函數時。 IAction 類型與IAction 無關,我得到異常。 – 2012-02-09 17:00:30

0

如何添加StateContainer到國家和行動:

public class ValidatingStateContainer<TState, TAction> : IStateContainer<TState, TAction> { 

    public ValidatingStateContainer(TState state) { 
     State = state; 
    } 

    public TState State { get; private set; } 

    public void Execute(TAction action) 
    { 
     if (action.IsValid(this)) 
      action.Apply(State); 
    } 
} 

public class ActionSet5IfZero : IAction<NumberState> 
{ 
    public boolean IsValid(NumberState state) 
    { 
     if (state.Number == 0) 
      return true; 
     else 
      return false; 
    } 

    public void Apply(NumberState state) 
    { 
     state.Number = 5; 
    } 
} 

public class ExtendedActionSet5IfZero : ActionSet5IfZero, IAction<TwoNumberState> 
{ 
    public boolean IsValid(TwoNumberState state) 
    { 
     if (base.IsValid(state) && state.Number2 == 0) 
      return true; 
     else 
      return false; 
    } 

    public void Apply(TwoNumberState state) 
    { 
     base.Apply(state); 
     state.Number2 = 5; 
    } 
} 

public class NumberState : IState { 
    public int Number { get; set; } 
} 

public class TwoNumberState : NumberState { 
    public int Number2 { get; set; } 
} 
1

,你可以:

public interface IStateContainer<TState, TAction> where TState : IState where TAction : IAction<TState> { 
    public TState State; 
    public void Execute(TAction action); 
} 

public interface IState { } 

public interface IAction<TState> where TState : IState { 
    bool IsValid(TState state); 
    void Apply(TState state); 
} 

然後你原來的類可以被替換添加一個虛擬的SetNumber方法到狀態

public class State 
{ 
    public int Number { get; set; } 

    public virtual void SetNumber(int n) 
    { 
     Number = n; 
    } 

    public void Execute(IAction action) 
    { 
     if (action.IsValid(this)) 
      action.Apply(this); 
    }    
} 

在擴展狀態下,你orverride它

public class ExtendedState : State { 
    public int Number2 { get; set; } 

    public orverride void SetNumber(int n) 
    { 
     base.SetNumber(n); 
     Number2 = n; 
    } 
} 

的行動將被這樣

public void Apply(State state)   
{ 
    state.SetNumber(5);   
}  

編輯實現:

有關聲明號碼

什麼作爲數組?

public class State 
{ 
    public int[] Numbers { get; private set; } 

    public State() 
    { 
     Numbers = new int[1]; 
    } 

    ... 
} 

的行動,那麼這是否

public void Apply(State state)   
{ 
    for (int i = 0; i < state.Numbers.Length; i++) { 
     state.Numbers[i] = 5; 
    } 
} 

ExtendedState的構造函數初始化Numbers

Numbers = new int[2]; 

此外,你可能對單數性質

public int Number { 
    get { return Numbers[0]; } 
    set { Numbers[0] = value; } 
} 

public int Number2 { 
    get { return Numbers[1]; } 
    set { Numbers[1] = value; } 
} 
+0

hanks奧利維爾迴應。問題是我有無數的動作,因此*命令模式*。你的解決方案不適合我的情況......我可以做一些關於Execute命令的虛擬化嗎? – 2012-02-09 16:54:54