我发现我经常写这样的代码:
class SomeClass
{
HandleOtherClass(OtherClass otherClass)
{
switch (otherClass.State)
{
case OtherClassState.Unstarted:
this.HandleUnstarted(situation);
break;
case OtherClassState.New:
this.HandleNew(situation);
break;
case OtherClassState.Ongoing:
this.HandleOngoing(situation);
break;
case OtherClassState.Stale:
this.HandleStale(situation);
break;
case OtherClassState.Complete:
this.HandleComplete(situation);
break;
default:
throw new NotImplementedException();
break;
}
}
}
它有效,但似乎我错过了一些可以使这段代码更易于维护的模式。我通常会在OO中读到if / switch语句应该被考虑在内。我考虑过一本字典,但只是将代码移动了一下而没有真正改变架构。我怎么能更好地处理这个?
答案 0 :(得分:1)
当您想扩展案例时,还有一些额外的复杂性需要考虑,特别是当您的同事没有参加过逻辑设计课程时:
HandleOtherClass(OtherClass otherClass)
{
switch (otherClass.State)
{
case OtherClassState.Unstarted:
// this can become quite complicated.
switch(yetAnotherState)
{
case 1:
//do stuff
break
case 2:
//etc
break;
}
break;
case OtherClassState.New:
this.HandleNew(situation);
break;
default:
throw new NotImplementedException();
break;
}
}
处理此重复设计问题的典型方法是state pattern。我必须说,它也可能变得非常麻烦,但拥有它至少会引导你进入“一个人”。状态机,而不是在任何地方重写代码,一般来说,我们力求可读性和可维护性。
以下是状态模式的典型包装示例(取自this实现),这些是常用的,因为它们的语法消除了类中已实现状态的复杂性:
var phoneCall = new StateMachine<State, Trigger>(State.OffHook);
phoneCall.Configure(State.OffHook)
.Permit(Trigger.CallDialled, State.Ringing);
phoneCall.Configure(State.Ringing)
.Permit(Trigger.CallConnected, State.Connected);
phoneCall.Configure(State.Connected)
.OnEntry(() => StartCallTimer())
.OnExit(() => StopCallTimer())
.Permit(Trigger.LeftMessage, State.OffHook)
.Permit(Trigger.PlacedOnHold, State.OnHold);
// ...
phoneCall.Fire(Trigger.CallDialled);
Assert.AreEqual(State.Ringing, phoneCall.State);
正如你所看到的,有states
(例如:OffHook),并且在这种状态下,通常通过事件(例如:PickedUp)转换到或不允许转换到另一个状态。发生此类转换时,将执行操作。
答案 1 :(得分:1)
现在的问题含糊不清。
如果需要状态模式,请在派生状态(例如NewState)上实现句柄。 调用对象的句柄,调用state.Handle()
如果要动态委托方法重载,请实现Handle(State1 s),Handle(State2 s)等。通过将状态转换为dynamic来调用它们,因此:Handle((dynamic)state)