我想实现一个命令模式。我有以下内容:
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;
}
}
这是我不喜欢的,因为实现接口的功能变得多余。此外,我需要在我的Execute
中创建一个新的ExtendedState
函数,该函数使用新类型而不是IAction(否则将调用未实现的函数)。
我相信它可以以一种不错的OO方式完成。你能帮我吗?目的是创建一个可扩展的State类和IAction接口(甚至可能是通用的,我不知道),所以我可以扩展State
但仍然是通用功能而无需额外的编码。
答案 0 :(得分:1)
您可以向状态
添加虚拟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);
}
}
在扩展状态下,你可以使用它
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);
}
修改强>:
将Number声明为数组怎么样?
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; }
}
答案 1 :(得分:0)
您可以使用泛型:
interface IAction<TState> where TState: State
{
bool IsValid(TState state);
void Apply(TState state);
}
答案 2 :(得分:0)
如何将StateContainer添加到State和Action:
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);
}
然后您的原始课程可以替换为:
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; }
}