重构:用Command替换条件调度程序
注:该随笔受启发于 《重构与模式》 第七章 第7.6小节 用Command替换条件调度程序 。
对于Command不做过多解释,这里我找了两个例子、供部分园友参阅:Command例子1 Command例子2 。
条件调度程序:我对这个名词的理解为,它是相对简单的选择结构 与 相对独立的业务逻辑的结合体。
话不是很好理解,下面举个小例子吧。
重构前的代码:
/// <summary> /// 很简单的选择分支 一层 if else /// N个 相对独立 任务 /// </summary> /// <param name="actionName"></param> public void DoAction(string actionName) { if (actionName == "Action1") { // 处理 Action1任务 Console.WriteLine("执行任务1"); } else if (actionName == "Action2") { // 处理 Action2任务 Console.WriteLine("执行任务2"); } else if (actionName == "Action3") { // 处理 Action3任务 // 无处理操作 } }
在 《重构与模式》 一文中的重构的做法是:
为每一个动作创建一个Command,把这些Command存储在一个集合中, 并用获取及执行Command的代码替换条件逻辑。
重构步骤我不做详细描述,看一下重构后的结果吧:
public class class2 { private Dictionary<string, CommandAbstract> dic; public class2() { this.dic = new Dictionary<string, CommandAbstract>(); this.dic.Add("Action1", new Command1()); this.dic.Add("Action2", new Command2()); this.dic.Add("Action3", new Command3()); } /// <summary> /// 应用 Command模式 替换 条件调度程序/// </summary> /// <param name="actionName"></param> public void DoAction(string actionName) { CommandAbstract command = null; if (dic.ContainsKey(actionName)) { command = dic[actionName]; } if (command != null) { command.Execute(); } } } public abstract class CommandAbstract { public abstract void Execute(); } public class Command1 : CommandAbstract { public override void Execute() { Console.WriteLine("执行任务1"); } } public class Command2 : CommandAbstract { public override void Execute() { Console.WriteLine("执行任务2"); } } public class Command3 : CommandAbstract { public override void Execute() { } }
看着 硬编码 Dictionary 很不爽,如果经常需要添加新Command, 有可能还需要继续重构——使其遵循开闭原则。
方案:使用反射代替硬编码 (简单的Plugin模式),重构后的结果如下:
public static class CommandFactory { private static Dictionary<string, CommandAbstract> dic; static CommandFactory() { dic = new Dictionary<string, CommandAbstract>(); Type absType = typeof(CommandAbstract); Assembly assem = absType.Assembly; foreach (Type t in assem.GetTypes()) { if (t.IsClass && !t.IsAbstract && t.IsSubclassOf(absType)) { CommandAbstract command = Activator.CreateInstance(t) as CommandAbstract; if (command != null && !dic.ContainsKey(command.CommandName)) { dic.Add(command.CommandName, command); } } } } public static CommandAbstract GetCommand(string commandName) { if (dic.ContainsKey(commandName)) { return dic[commandName]; } return null; } } public class class2 {/// <summary> /// 重构硬编码/// </summary> /// <param name="actionName"></param> public void DoAction(string actionName) { CommandAbstract command = CommandFactory.GetCommand(actionName); if (command != null) { command.Execute(); } } } public abstract class CommandAbstract { public string CommandName { get; protected set; } public abstract void Execute(); } public class Command1 : CommandAbstract { public Command1() { this.CommandName = "Action1"; } public override void Execute() { Console.WriteLine("执行任务1"); } } public class Command2 : CommandAbstract { public Command2() { this.CommandName = "Action2"; } public override void Execute() { Console.WriteLine("执行任务2"); } } public class Command3 : CommandAbstract { public Command3() { this.CommandName = "Action3"; } public override void Execute() { } }
如果 条件表达式 较为复杂呢,那又可以怎样重构?
提示:责任链模式。