由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可以看出一个产品 ...
随机推荐
- C# Redis之ServiceStack
前面几篇博客基本把redis基本操作学习了下,但一些高级应用并没有写进博客,例如持久化.虚拟内存等,像这些主要是通过配置文件来解决的,运维方向可能更侧重一些,对于开发者来说,可能就想知道怎么用C#来和 ...
- SQLHelper帮助类_下(支持多数据库的封装)
在上篇关于SQLHelper类中,主要针对SQLServer数据库进行的.在使用别的数据库,就要修改部分代码!所以今天就写一个支持多数据库的封装!主要用到枚举,读取config文件!接口的简单用法.获 ...
- webpack配置React开发环境(上)
Webpack 是一个前端资源加载/打包工具,我们部门的一条主要技术栈就是Webpack+React+ES6+node,虽然之前自己做个人项目也接触好多次Webpack,但是自己并没有研读总结过Web ...
- 学习HTML5一周的收获1
HTML5的基本结构 学习了title标签(显示网站名称),link标签(链接文件,可做网页美化) 快捷键:Ctrl+/ 注释 学习[meta标签] 1.charset属性:单独使用,设置文档字符集编 ...
- 关于mvc中传入DataTable到视图的应用
MVC 中 如果是多表连接查询出的数据需要重新定义一个ViewModel,觉得很是麻烦,所以可以通过传一个DataTable到视图中可以避免这个问题 但是不知道会有什么不好的地方,有这方面经验的大神有 ...
- 浅谈HTML5中的浮动问题
浮动是我们在前端页面中经常会用到的一种布局方式.那什么是浮动呢? 首先我们先来看一下它的定义.浮动是指让元素脱离文档标准流(脱标),按照指定的方向去横向排列.浮动的取值有两个,分别是float:lef ...
- Spring IOC容器中Bean的生命周期
1.IOC容器中Bean的生命周期 构造器函数 设置属性 初始化函数(在Bean配置中 init-method) 使用Bean 结束时关闭容器(在Bean中配置destroy-method) 2.Be ...
- 自学spring过程中碰到的问题list,一个一个解决
1.spring的基本原理 2.spring注解有哪几种方式 3.什么情况下适合用哪种注解 4.@autowired @Resource 等的区别 5.spring是怎么使用反射的 6.cjlibe ...
- 对VC++6.0爱得深沉(一)安装vc++6.0,支持winXP,win7,win8.1,win10
[欢迎入坑] 从这里起,我称VC++6.0为小c. 为什么我对小c爱得深沉? 虽然饱受非议,但是,我只想说,我太单纯,小c轻轻松松成功运行在各个win平台,对于我来说她:高速.小巧.便捷.听话.可定制 ...
- SQL AlawaysOn 之四:故障转移集群
声明,故障转移集群,仅安装在SQL服务器中,域服务器不能和SQL服务器一起加入集群. 1.添加故障转移集群,下一步 2.安装 3.在域控制服务器上的管理工具里打开故不障转移集群管理器,选择创建集群 4 ...