質問を強調するために、私は特別に不変の単語と突然変異で遊んだ。
状態遷移をモデル化し、関連データを収集する抽象化をプロパティ設計したいと思います(おそらく、この2つの要件は単一責任に違反していますか?)。
私は次のようなものをスケッチします:
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" }));
前の質問から、 .NET不変コレクションを使用できることがわかりました。
しかし、これはここでの私の質問の中心ではありません。そのような設計が、関連データの遷移をモデル化する不変のデータ構造の正しい(または許容可能な)実装につながるかどうかを知りたいです。
代替実装:
列挙を削除して、Stateのサブタイプを定義できますか?
class State {
public StateTransition1 ChangeToTransition1() {
return new StateTransition1( ... );
}
public StateTransition2 ChangeToTransition2(IEnumerable data) {
return new StateTransition2( ... );
}
}
このように、私は、transition1が明確に定義された特定の意味であり、transition2がそれ自体である(たとえば、特定の関連データが含まれている)ことを明確に示しています。
次に、コンシューマーコードは、フローを制御するために列挙型ではなくサブタイプタイプをクエリできます。
状態変更方法を適切に因数分解する:
状態はコンストラクターを使用して再作成されるため、拡張メソッドとしての因数分解( `` ChangeToXXXX`)変更状態メソッドが、より保守可能で正式な正しい設計につながる可能性があるのではないかと思います。