重构:用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()
{ }
}
如果 条件表达式 较为复杂呢,那又可以怎样重构?
提示:责任链模式。
重构:用Command替换条件调度程序的更多相关文章
- 重构第四天 : 用多态替换条件语句(if else & switch)
面相对象的一个核心基础就是多态,当你要根据对象类型的不同要做不同的操作的时候,一个好的办法就是采用多态,把算法封装到子类当中去. 重构前代码: public abstract class Custom ...
- 重构与模式 (Joshua Kerievsky 著)
第1章 本书的写作缘由 第2章 重构 第3章 模式 第4章 代码坏味 第5章 模式导向的重构目录 第6章 创建 第7章 简化 第8章 泛化 第9章 保护 第10章 聚集操作 第11章 实用重构 参考文 ...
- 如何解决代码中if…else 过多的问题
前言 if...else 是所有高级编程语言都有的必备功能.但现实中的代码往往存在着过多的 if...else.虽然 if...else 是必须的,但滥用 if...else 会对代码的可读性.可维护 ...
- 你还在 if...else?代码这样写才好看!
前言 if...else 是所有高级编程语言都有的必备功能.但现实中的代码往往存在着过多的 if...else.虽然 if...else 是必须的,但滥用 if...else 会对代码的可读性.可维护 ...
- 如何解决代码中if/else 过多的问题
前言 if...else 是所有高级编程语言都有的必备功能.但现实中的代码往往存在着过多的 if...else.虽然 if...else 是必须的,但滥用 if...else 会对代码的可读性.可维护 ...
- 重构与模式(Refactoring to Patterns)-读书笔记
第一章 ☛过度设计:是指代码的灵活性和复杂性超出所需. 第二章 ☛重构是一种保持行为的转换. 第三章 ☛每一个模式都是由三部分组成的规则,他表达的是某一环境,一个问题以及解决问题的方案之间的关系. ☛ ...
- C#重构之道
定义 重构的定义:在不改变软件可观察行为的前提下,改善其内部结构. 其中,不改变软件行为,是重构最基本的要求.要想真正发挥威力,就必须做到“不需了解软件行为”. 如果一段代码能让你容易了解其行为,说明 ...
- 《Code Complete》ch.24 重构
WHAT? 重构(refactoring),Martin Fowler将其定义为“在不改变软件外部行为的前提下,对其内部结构进行改变,使之更容易理解并便于修改”. WHY? 神话:一个管理很完善的软件 ...
- 重构:越来越长的 switch ... case 和 if ... else if ... else
在代码中,时常有就一类型码(Type Code)而展开的如 switch ... case 或 if ... else if ... else 的条件表达式.随着项目业务逻辑的增加及代码经年累月的修改 ...
随机推荐
- Javascript自己动手实现getter/setter
虽然ES5中为我们提供了Object.defineProperty方法来设置getter与setter,但此原生方法使用起来并不方便,我们何不自己来实现一个类,只要继承该类并遵循一定的规范就可以拥有媲 ...
- 【T-SQL基础】03.子查询
以前总是追求新东西,发现基础才是最重要的,今年主要的目标是精通SQL查询和SQL性能优化. 本系列[T-SQL基础]主要是针对T-SQL基础的总结. [T-SQL基础]01.单表查询-几道sql查询题 ...
- Nim教程【十】
openarray类型 注意:openarray类型只能用于参数 固定大小的数组虽然性能不错,但过于呆板,使用取来不是很方便 对于一个方法来说,传入参数如果是一个数组,最好是不要限制数组的长度 也就是 ...
- SVM-非线性支持向量机及SMO算法
SVM-非线性支持向量机及SMO算法 如果您想体验更好的阅读:请戳这里littlefish.top 线性不可分情况 线性可分问题的支持向量机学习方法,对线性不可分训练数据是不适用的,为了满足函数间隔大 ...
- 可拖动的DIV续
之前写过一篇可拖动的DIV讲如何实现可拖动的元素,最后提出了几点不足,这篇文章主要就是回答着三个问题 1. 浏览器兼容性 2. 边界检查 3. 拖动卡顿.失灵 先附上上次代码 <!DOCTYPE ...
- Git Day03,GitHub 1st
1st, SSH key: Add a pic @ Sep 18 2016 20:26 To note the configuration process on Linux: 2nd,github网站 ...
- Java-继承,多态-0922-04
定义类Human,具有若干属性和功能:定义其子类Man.Woman: 在主类Test中分别创建子类.父类和上转型对象,并测试其特性. 父类: package com.lianxi3; public c ...
- salesforce 零基础学习(二十五)PickList简单联动操作
有的时候,项目需要一些联动的操作,比如省和市之间的联动,不同的省应该显示不同的城市. 操作步骤如下: 1.新建provice字段,并且初始化相关的值 2.新建city字段,并且初始化相关的值 3.在P ...
- WPF入门教程系列十二——依赖属性(二)
二. 依赖属性的优先级 由于WPF 允许我们可以在多个地方设置依赖属性的值,所以我们就必须要用一个标准来保证值的优先级别.比如下面的例子中,我们在三个地方设置了按钮的背景颜色,那么哪一个设置才会是最终 ...
- Java 多态——与C++的比较
学习了Java和C++之后,由于长期不使用C++,而java的基础知识掌握不牢,现在已经搞不清java多态了.现在先来谈谈java多态,稍后有时间再更新C++的多态,并进行比较~ 一. Java的多态 ...