由if-else,switch代替方案引起的思考
关键词:条件判断,多态,策略模式,哈希表,字典map
作者:码匠信龙
笔者在用python实现事件驱动后,发现python是没有提供switch语句,python官方推荐多用字典来代替switch来实现,这让我就觉得有点奇怪了。我们在编写多分支结构的程序,一般编程语言都有提供会选择if-else或者switch-case语句。条件少的时候还可以,当分支结构过分长,就会导致代码不美观且不容易维护。在笔者的从业工作经验中,多次看到项目在网络消息处理和gui层消息处理代码中,有超过20多条的if-else,switch-case语句,导致函数代码非常长。
例如下面这段类似windows消息处理的伪代码
void WndProc(hWnd, message, wParam, lParam)
{
switch (message)
{
case WM_CREATE:
{
button1 = CreateWindow("button");
}
break;
case WM_COMMAND:
switch (cmdID)
{
case btn1:
MessageBox("XXXX");
break;
case btn2:
MessageBox("XXXX");
break;
case IDM_TEST:
MessageBox("XXXX");
break;
case IDM_ABOUT:
DialogBox("XXXX");
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return;
}
break;
case WM_PAINT:
dosomething();
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return;
}
return 0;
}
如果有100个消息ID,那就要写100个case的处理(经验不足的新手有时候甚至少写break关键字),整个WndProc函数就非常的长了。
而用python的字典实现的话,把消息处理函数映射到消息ID,伪代码如下
messages = {}
#绑定消息处理函数和消息ID
messages[WM_CREATE] = fun1;
messages[WM_PAINT] = fun2;
...
def WndProc(self,message):
if message.type in messages.keys():
listener = messages[message.type]
listener(message)
读者可以看到,整个WndProc就变成几行代码,消息处理函数的定义和绑定可以在其它地方实现,不需要全部都堆在一块,使得分支判断逻辑和细节处理函数分离了,而且提高了代码可读性和扩展性。高内聚,低耦合,这是编程开发中很重要的一种思想,上面例子说明了如何解耦分支逻辑和处理函数。
在笔者也曾在一个开源UI编辑器的源码中看过在gui层,解析ui配置文件生成界面的实现上也有类似的实现。
在《重构》一书中,专门有一章是内容讲解“简化条件表达式”,里面就有讲到利用多态取代条件表达式。而多态应用场景正是当对象要根据不同的状态表现不同的行为时使用的。java经常讲很多设计模式中都有用到多态的特性,以前看java项目代码发现很少有用到很多if-else和switch-case的代码段,反而经常看到很多用多态实现的类,通过继承抽象类,重写抽象方法的方式,来避免使用了条件语句。
突然想起C++的多态实现,虚函数表,存的是虚函数的指针,也就是虚函数的地址,也是通过数组或哈希表来存储(数组其实也是一种哈希表)。冥冥之中好像它们之间有着某种联系。
读到这里,你会发现字典(哈希表)map是很神奇一种数据结构,再多考虑一步:
1.map的value中保存的不再是基本数据类型,而是对象。这样一来,通过不同的key可以拿到不同的对象,如果这些对象的类都实现同一个接口,那么这就是一个加强版的策略模式,就是多态性的体现,传统的策略模式传入的是实现类的对象,而通过map加强,只需传入一个数字或字符串即可实现多态。
2.map的value中保存的是函数,通过不同的key(消息类型)可以拿到不同的响应处理函数,则可以实现消息机制或事件驱动。
字典只是一种数据结构,但通过不同的变化,却可以用更简单的方式实现某些设计模式或面向对象的多态特性,以至于让笔者觉得如何锻炼抽象业务逻辑和解耦代码的能力,才是一种更简单自然的编程方式,没有一种固定的编程范式,学习某某设计模式反而固化了编程思维。
虽然if-else和switch很常见的关键字,但不知读者是否也能停下来思考一下。
版权声明:本文为博主原创,欢迎转载分享,只需注明作者与出处http://thinkingroom.me
由if-else,switch代替方案引起的思考的更多相关文章
- MapReduce源码分析之Task中关于对应TaskAttempt存储Map方案的一些思考
我们知道,MapReduce有三层调度模型,即Job——>Task——>TaskAttempt,并且: 1.通常一个Job存在多个Task,这些Task总共有Map Task和Redcue ...
- 构建iOS稳定应用架构时方案选择的思考,主要涉及工程结构,数据流思想和代码规范
工程结构架构,减少耦合混乱以及防治需求大改造成结构重构,如何构建稳定可扩展可变换的工程结构的思考 我打算采用Information flow的方式自上而下,两大层分为基础层和展现层的结构.基础层分为多 ...
- Dataguard配置总结
Dataguard配置总结 本例情形 在主库存在运行的情况下,增加配置dataguard备库,实现双机热备,高可用性. 主库要求,归档模式,强制归档. 主库idty 备库idty_st 1.密码文件 ...
- python 基础部分重点复习整理--从意识那天开始进阶--已结
pythonic 风格编码 入门python好博客 进阶大纲 有趣的灵魂 老齐的教程 老齐还整理了很多精华 听说 fluent python + pro python 这两本书还不错! 元组三种遍历, ...
- 提升代码幸福度,五个技巧减少js开发中的if else语句
壹 ❀ 引 在JavaScript开发中,条件判断语句的使用频率是极高的,而对于条件判断简单易读的if else应该都是大家的首选.可是代码写的久了,我们总是希望自己的代码看着能更为简洁规范(逼格更 ...
- 【译】Redux 还是 Mobx,让我来解决你的困惑!
原文地址:Redux or MobX: An attempt to dissolve the Confusion 原文作者:rwieruch 我在去年大量的使用了 Redux,但我最近都在使用 Mob ...
- You must use the Role Management Tool to install or configure Microsoft .NET Framework 3.5 SP1
今天在Windows Server 2008 下安装SQL SERVER 2008时,碰到如下错误: You must use the Role Management Tool to install ...
- 【腾讯Bugly干货分享】微信终端跨平台组件 mars 系列(一) - 高性能日志模块xlog
本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57ff5932cde42f1f03de29b1 本文来源: 微信客户端开发团队 ...
- 如何撰写PRD
PRD(Product-Requirement-Document,产品需求文档),这对于任何一个产品经理来说都不会陌生的一个文档,一个PRD是衡量一个产品经理整体思维的标准,一个PRD可以看出一个产品 ...
随机推荐
- 【Scala】Scala之Object
一.前言 前面学习了Scala的Methods,接着学习Scala中的Object 二.Object Object在Scala有两种含义,在Java中,其代表一个类的实例,而在Scala中,其还是一个 ...
- gridview中后台获取某列的值
下面的gridview中,获取某行某列的值(非模板页),如图所示 <asp:GridView AutoGenerateColumns="false" CssClass=&qu ...
- Day01 Java环境变量配置
1. Java环境配置的确浪费了一些时间,网上找的资料在设置PATH.CLASSPATH几乎都是利用的JAVA_HOME的路径 例如CLASSPATH=.;%JAVA_HOME%\lib;%JAVA_ ...
- Java面试系列
如果你的面试简历是如下这样写的,请务必准备回答下面的所有问题. 面试职位:Java高级工程师 专业技能: (1)牢固掌握Java基础知识,如集合.并发.I/O等,并对Java源码有一定的研究. (2) ...
- 在.NET项目中使用PostSharp,使用MemoryCache实现缓存的处理
在之前一篇随笔<在.NET项目中使用PostSharp,实现AOP面向切面编程处理>介绍了PostSharp框架的使用,试用PostSharp能给我带来很多便利和优势,减少代码冗余,提高可 ...
- 3399: [Usaco2009 Mar]Sand Castle城堡
3399: [Usaco2009 Mar]Sand Castle城堡 Time Limit: 3 Sec Memory Limit: 128 MBSubmit: 37 Solved: 32[Sub ...
- a中的类型转换
自动类型转换 当然自动类型转换是需要满足特定的条件的: 1. 目标类型能与源类型兼容,如 double 型兼容 int 型,但是 char 型不能兼容 int 型. 2. 目标类型大于源类型,如 ...
- cobbler自动安装系统
一.简介 Cobbler是一个快速网络安装linux的服务,而且在经过调整也可以支持网络安装windows.该工具使用python开发,小巧轻便(才15k行python代码),使用简单的命令即可完成P ...
- webpack 打包js和css
首先进行全局安装webpack npm install -g webpackcmd跳转到项目的文件夹,安装webpack npm install --save-dev webpack接着需要packj ...
- NoSQL注入的分析和缓解
本文要点介绍: 1.了解针对NoSQL的新的安全漏洞 2.五类NoSQL攻击手段,比如重言式.联合查询.JavaScript 注入.背负式查询(Piggybacked queries),以及跨域违规 ...