想到了几个解决方案,它们可以实现完全 SOLID 的解决方案。
解决方案 1
满足依赖倒置原则的第一个也是最简单的方法是将Run 类注入Walk 类,如下所示:
public class Walk : IState
{
float speed = 10;
private readonly IState _runState;
public Walk(IState runState)
{
_runState = runState;
}
public IState CheckForState()
{
if (speed > 5)
{
return _runState;
}
return this;
}
}
这个解决方案使得 Walk 不再依赖于 Run 的具体实现,但仍然允许它转换到运行状态。但是,这确实需要Walk 知道它可以转换到哪些状态(我认为这是一个合理的预期)。
解决方案 2
您可以通过将状态转换表示为对象来进一步解耦。这看起来像这样:
public interface IState
{
public IState CheckForState();
public float Value {get;}
}
public interface IStateTransition
{
public IState CheckTransition(IState source);
}
public class GreaterThanTransition : IStateTransition
{
private readonly IState _targetState;
private readonly int _checkValue;
public GreaterThanTransition(IState targetState, int checkValue)
{
_targetState = targetState;
_checkValue = checkValue;
}
public IState CheckTransition(IState sourceState) => sourceState.Value > _checkValue ? _targetState : sourceState;
}
public class Walk : IState
{
private readonly List<IStateTransition> _transitions;
public Walk(List<IStateTransition> transitions)
{
_transitions = transitions;
}
public float Value => 10;
public IState CheckForState() => _transitions.Select(t => t.CheckTransition(this)).FirstOrDefault(s => s != this) ?? this;
}
然后你可以像这样创建一个 Walk 实例:
new Walk(new List<IStateTransition>
{
new GreaterThanTransition(new Run(...), 5)
});
这要求可以在IStateTransition 中使用来自状态对象的值来检查是否需要发生状态转换。我在示例中使用了int 作为Value 属性的类型,但您可以轻松地将其切换为泛型类型。
该解决方案将每个状态完全解耦,并将状态转换捕获为可重用组件。它在某些方面更加复杂,因为代码现在被拆分为更多的类和接口,但它也完全结合了 SOLID 原则。