重构:用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 的条件表达式.随着项目业务逻辑的增加及代码经年累月的修改 ...
随机推荐
- (小常识)Dictionary的遍历
Dictionary<int, string> objDictionary = new Dictionary<int, string>(); ...
- [Unity3D]做个小Demo学习Input.touches
[Unity3D]做个小Demo学习Input.touches 学不如做,下面用一个简单的Demo展示的Input.touches各项字段,有图有真相. 本项目已发布到Github,地址在(https ...
- 据说每个大牛、小牛都应该有自己的库——JavaScript原生对象拓展
在据说每个大牛.小牛都应该有自己的库——框架篇中我扬言要做个小牛,没想到一天没更新,小伙儿伴们就戏谑的问我,油哥是不是要太监了?其实事情是这个样子的,这不是太监的节奏,一是,关于写个自己的库的想法由来 ...
- Linux网络编程系列-TCP编程实例
实例: client #include <stdio.h> #include <sys/socket.h> #include <netinet/in.h> #inc ...
- Java-类和对象基础练习
1.创建一个三角形类,成员变量三边,方法求周长,创建类主类A来测试它. package liu0919; public class Sanjiao { public double z(double a ...
- H5常用代码:适配方案3
在H5项目中有一种常见的宣传页,就是那种整屏整屏的,带着炫丽进场动画的移动宣传页,不仅是一种欣赏也起到了很大宣传作用. 对于这种整屏的适配,前面通过视口的兼容处理也是可以做到的,但是在窄屏下会在上下有 ...
- [数据库事务与锁]详解八:底理解数据库事务乐观锁的一种实现方式——CAS
注明: 本文转载自http://www.hollischuang.com/archives/1537 在深入理解乐观锁与悲观锁一文中我们介绍过锁.本文在这篇文章的基础上,深入分析一下乐观锁的实现机制, ...
- Atitit usrqbg1834 html的逻辑化流程化 规范标准化解决方案
Atitit usrqbg1834 html的逻辑化流程化 规范标准化解决方案 常用指令1 ..v-if.v-else指令2 v-for指令3 MVVM大比拼4 常用指令 本来按照Vue文档说明,常用 ...
- SSM环境搭建(接口编程方式)
一直用ssm在开发项目,之前都是直接copy别人的项目,今天趁着项目刚刚交付,自己搭建一下ssm环境,做个记录 一.创建项目.引入jar包,因为版本不一样,就不贴出这部分的内容了.个人平时的习惯是,先 ...
- 封装WebAPI客户端,附赠Nuget打包上传VS拓展工具
一.前言 上篇< WebAPI使用多个xml文件生成帮助文档 >有提到为什么会出现基于多个xml文件生成帮助文档的解决方案,因为定义的模型可能的用处有: 1:单元测试 2:其他项目引用(可 ...