关键词:条件判断,多态,策略模式,哈希表,字典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代替方案引起的思考的更多相关文章

  1. MapReduce源码分析之Task中关于对应TaskAttempt存储Map方案的一些思考

    我们知道,MapReduce有三层调度模型,即Job——>Task——>TaskAttempt,并且: 1.通常一个Job存在多个Task,这些Task总共有Map Task和Redcue ...

  2. 构建iOS稳定应用架构时方案选择的思考,主要涉及工程结构,数据流思想和代码规范

    工程结构架构,减少耦合混乱以及防治需求大改造成结构重构,如何构建稳定可扩展可变换的工程结构的思考 我打算采用Information flow的方式自上而下,两大层分为基础层和展现层的结构.基础层分为多 ...

  3. Dataguard配置总结

    Dataguard配置总结 本例情形 在主库存在运行的情况下,增加配置dataguard备库,实现双机热备,高可用性. 主库要求,归档模式,强制归档. 主库idty 备库idty_st 1.密码文件 ...

  4. python 基础部分重点复习整理--从意识那天开始进阶--已结

    pythonic 风格编码 入门python好博客 进阶大纲 有趣的灵魂 老齐的教程 老齐还整理了很多精华 听说 fluent python + pro python 这两本书还不错! 元组三种遍历, ...

  5. 提升代码幸福度,五个技巧减少js开发中的if else语句

     壹 ❀ 引 在JavaScript开发中,条件判断语句的使用频率是极高的,而对于条件判断简单易读的if else应该都是大家的首选.可是代码写的久了,我们总是希望自己的代码看着能更为简洁规范(逼格更 ...

  6. 【译】Redux 还是 Mobx,让我来解决你的困惑!

    原文地址:Redux or MobX: An attempt to dissolve the Confusion 原文作者:rwieruch 我在去年大量的使用了 Redux,但我最近都在使用 Mob ...

  7. 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 ...

  8. 【腾讯Bugly干货分享】微信终端跨平台组件 mars 系列(一) - 高性能日志模块xlog

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57ff5932cde42f1f03de29b1 本文来源: 微信客户端开发团队 ...

  9. 如何撰写PRD

    PRD(Product-Requirement-Document,产品需求文档),这对于任何一个产品经理来说都不会陌生的一个文档,一个PRD是衡量一个产品经理整体思维的标准,一个PRD可以看出一个产品 ...

随机推荐

  1. chrome浏览器美化插件:让你的浏览器页面冒水泡, 游小鱼儿

    下载插件和效果图 这是一个让你的浏览器冒泡泡的插件, 浏览网页的时候仿佛置身于海底世界: 插件下载地址:http://files.cnblogs.com/files/diligenceday/chro ...

  2. 2017-3-2 C#基础 结构体

    1. 结构体:用户自定义类型定义位置:定义在Main函数的外面,类的里面 定义格式:struct 自定义名字{ public 数据类型 名字; public 数据类型 名字; ... ...} 声明实 ...

  3. 卷积神经网络(CNN)反向传播算法

    在卷积神经网络(CNN)前向传播算法中,我们对CNN的前向传播算法做了总结,基于CNN前向传播算法的基础,我们下面就对CNN的反向传播算法做一个总结.在阅读本文前,建议先研究DNN的反向传播算法:深度 ...

  4. 代写编程的作业、笔试题、课程设计,包括但不限于C/C++/Python

    代写编程作业/笔试题/课程设计,包括但不限于C/C++/Python 先写代码再给钱,不要任何定金!价钱公道,具体见图,诚信第一! (截止2016-11-22已接12单,顺利完成!后文有成功交付的聊天 ...

  5. TypeScript设计模式之工厂

    看看用TypeScript怎样实现常见的设计模式,顺便复习一下. 学模式最重要的不是记UML,而是知道什么模式可以解决什么样的问题,在做项目时碰到问题可以想到用哪个模式可以解决,UML忘了可以查,思想 ...

  6. [ZooKeeper.net] 1 模仿dubbo实现一个简要的http服务的注册 基于webapi

    今天来试着模仿下dubbo实现一个简要的http服务的注册,虽说是模仿不过是很廉价的那种,只是模仿了一点点点...... 先放上demo目录结构: 开头还是把ZooKeeper的一些简要介绍搬过来看看 ...

  7. 深入理解 JavaScript 异步系列(3)—— ES6 中的 Promise

    第一部分,Promise 加入 ES6 标准 原文地址 http://www.cnblogs.com/wangfupeng1988/p/6515855.html 未经作者允许不得转载! 从 jquer ...

  8. MySQL学习分享-->查询-->查询的原理

    查询的原理 在一个查询中常包含下述子句: 1.select,2.distinct,3.join,4.on,5.from,6.where,7.having,8.group by,9.order by,1 ...

  9. Mditor 发布「桌面版」了 - http://mditor.com

    简单说明 Mditor 最早只有「组件版」,随着「桌面版」的发布,Mditor 目前有两个版本: 可嵌入到任意 Web 应用的 Embed 版本,这是一桌面版的基础,Repo: https://git ...

  10. 好多鱼 Java

    牛客网的题目: 链接:https://www.nowcoder.com/questionTerminal/e3dd485dd23a42899228305658457927牛牛有一个鱼缸.鱼缸里面已经有 ...