根据一些文章:
该理论认为这很容易,但实际上这通常很困难。 没关系。让我们了解这件事的核心。
代码如下所示:
public class SomeType
{
// Some properties.
}
public enum SomeTrigger
{
Loaded,
Initial,
Timer,
Final
}
public class SomeBaseObject
{
//
// I am not allowed to change this class. It is not mine.
//
protected Dictionary<string, SomeType> Input;
protected Dictionary<string, SomeType> Output;
// Timer is evaluated every 2 sec.
public virtual void Execute(SomeTrigger trigger, string value)
{
switch (trigger)
{
case SomeTrigger.Loaded:
break;
case SomeTrigger.Initial:
break;
case SomeTrigger.Timer:
break;
case SomeTrigger.Final:
break;
default:
break;
}
}
// The rest of code...
}
我要改进的课程:
public class SomeSpecificObject : SomeBaseObject
{
private bool isInitializationCompleted;
private string connection;
public override void Execute(SomeTrigger trigger, string value)
{
switch (trigger)
{
case SomeTrigger.Loaded:
this.OnLoaded();
break;
case SomeTrigger.Initial:
this.OnInitial();
break;
case SomeTrigger.Timer:
this.OnTimer();
break;
case SomeTrigger.Final:
this.OnFinal(value);
break;
default:
break;
}
}
private void OnLoaded()
{
// Read Input and Output collection.
}
private void OnInitial()
{
// Initialization (connect to the server).
// Bla bla bla
this.connection = //Value from the plug-in;
this.isInitializationCompleted = true;
}
private void OnTimer()
{
if (isInitializationCompleted)
{
// Do something
// Connection is using here.
// Calculate values on a Input collection, etc.
}
}
private void OnFinal(string value)
{
if (isInitializationCompleted)
{
// something with "value"
// Connection is using here.
// Clear state.
}
else
{
// Connection is using here.
// Cancel inistialization
}
}
}
我该怎么办?每个领域都在使用但每个触发器。另外,一个案例有点具体(OnFinalMethod需要参数)。基于上面的文章,我试图重构这段代码,但没有成功。
My attempts to apply some tips:
public interface ITrigger
{
void Execute();
}
public class LoadedTrigger : ITrigger
{
public void Execute()
{
throw new NotImplementedException();
}
}
//
// Exactly the same class for the rest cases.
//
public class TriggerHandler
{
private Dictionary<SomeTrigger, ITrigger> triggerDictionary;
public TriggerHandler()
{
triggerDictionary.Add(SomeTrigger.Loaded, new InitialTrigger());
// and for the rest
}
public void HandleTrigger(SomeTrigger trigger)
{
triggerDictionary[trigger].Execute();
}
}
对象如何相互通信?例如。 TimerTrigger对象需要知道启动成功。我该如何处理特殊情况对象?
有什么想法吗? :)
答案 0 :(得分:1)
首先,一般来说,switch语句没有任何问题。只是在代码中使用它会产生一些隐含的结构限制。如果其中一个限制与代码演变的方式相矛盾,换句话说,如果需求以切换逻辑变得过时的方式发生变化,那么继续在代码中使用它会导致技术债务。
从上面的代码中不清楚它的要求是什么。例如,为什么要求首先使用Execute方法?它可以直接替换为Loaded(),Initial()和其他方法吗?这显然会消除转换。
另一种方法是使用事件对象而不是枚举并使用方法重载:执行(LoadedTrigger ...),...,执行(FinalTrigger ...,...)。
如果你想在运行时添加处理程序,那么使用字典的方法很好(对吗?),但缺少的部分是检查触发器类型并调用不同的execute方法:
var t = triggerDictionary[trigger];
if (t is SimpleTrigger st) st.Execute();
else if (t is AdvancedTrigger at) at.Execute(value);
或者,为触发器的execute方法添加值。但如果没有这样的要求,为什么要打扰?
E.g。 TimerTrigger对象需要知道启动成功。
您可能想要一台状态机。 switch是一种经常用于编码简单状态机转换的方法。
答案 1 :(得分:0)
作为其中一种方法,您可以使用template method。使用此模式,您的代码将如下所示:
public class SomeType
{
// Some properties.
}
public enum SomeTrigger
{
Loaded,
Initial,
Timer,
Final
}
public abstract class SomeBaseObject
{
//
// I am not allowed to change this class. It is not mine.
//
protected Dictionary<string, SomeType> Input;
protected Dictionary<string, SomeType> Output;
// Timer is evaluated every 2 sec.
public void Execute(SomeTrigger trigger, string value)
{
switch (trigger)
{
case SomeTrigger.Loaded:
OnLoaded();
break;
case SomeTrigger.Initial:
OnInitial();
break;
case SomeTrigger.Timer:
OnTimer();
break;
case SomeTrigger.Final:
OnFinal(value);
break;
default:
break;
}
}
protected abstract void OnLoaded();
protected abstract void OnInitial();
protected abstract void OnTimer();
protected abstract void OnFinal(string value);
}
public class SomeSpecificObject : SomeBaseObject
{
private bool isInitializationCompleted;
private string connection;
protected override void OnLoaded()
{
// Read Input and Output collection.
}
protected override void OnInitial()
{
// Initialization (connect to the server).
// Bla bla bla
this.connection = "";//Value from the plug-in;
isInitializationCompleted = true;
}
protected override void OnTimer()
{
if (isInitializationCompleted)
{
// Do something
// Connection is using here.
// Calculate values on a Input collection, etc.
}
}
protected override void OnFinal(string value)
{
if (isInitializationCompleted)
{
// something with "value"
// Connection is using here.
// Clear state.
}
else
{
// Connection is using here.
// Cancel inistialization
}
}
}
如果需要,您可以提供OnXXX方法的默认实现并将其标记为虚拟