我特别玩了不可变和突变的词来突出这个问题。
我想设计一个抽象来模拟状态转换并收集相关数据(也许这两个要求违反了单一职责?)。
我会画出类似的东西:
enum StateTypeEnum
{
State1,
State2,
State3
}
class State
{
private readonly StateTypeEnum _stateType;
private readonly IEnumerable<string> _stateData;
public State(StateTypeEnum stateType)
{
_stateType = stateType;
_stateData = new List<string>(new string[] { });
}
public State(StateTypeEnum stateType, IEnumerable<string> stateData)
{
_stateType = stateType;
_stateData = new List<string>(stateData);
}
public State ChangeState(StateTypeEnum stateType)
{
return new State(stateType, _stateData);
}
public State ChangeState(StateTypeEnum stateType, IEnumerable<string> stateData)
{
return new State(stateType, _stateData.Concat(stateData));
}
public State ChangeState(IEnumerable<string> stateData)
{
return new State(_stateType, _stateData.Concat(stateData));
}
public IReadOnlyList<string> StateData
{
get
{
return new ReadOnlyCollection<string>(_stateData.ToList());
}
}
public StateTypeEnum CurrentStateType
{
get
{
return _stateType;
}
}
}
并将其用作:
var state1 = new State(StateTypeEnum.State1);
var state2 = state1.ChangeState(StateTypeEnum.State3);
var state3 = state2.ChangeState(new[] { "a", "b", "c" });
var state4 = state3.ChangeState(StateTypeEnum.State1, new[] { "d", "e" });
var state5 = state4.ChangeState(StateTypeEnum.State3);
Debug.Assert(
state5.CurrentStateType == StateTypeEnum.State3);
Debug.Assert(
state5.StateData.SequenceEqual(new[] { "a", "b", "c", "d", "e" }));
但这不是我的问题的核心,我想知道这样的设计是否会导致不可变数据结构的正确(或可接受)实现,该结构模型状态与相关数据的转换。
替代实现:
我可以删除枚举并定义 State 的子类型吗?
class State {
public StateTransition1 ChangeToTransition1() {
return new StateTransition1( ... );
}
public StateTransition2 ChangeToTransition2(IEnumerable data) {
return new StateTransition2( ... );
}
}
通过这种方式,我清楚地将transition1 作为定义明确的特定含义,将transition2 作为它自己的含义(例如,它包含特定的关联数据)。
然后消费者代码可以查询子类型类型而不是枚举来控制流程。
正确考虑状态变化方法:
由于使用构造函数重新创建状态,我想知道分解(``ChangeToXXXX`)是否将状态方法更改为扩展方法可以导致更可维护和更正式的正确设计。