由if-else,switch代替方案引起的思考
来源:互联网 发布:石家庄淘宝摄影 编辑:程序博客网 时间:2024/06/05 01:02
关键词:条件判断,多态,策略模式,哈希表,字典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 = {}#绑定消息处理函数和消息IDmessages[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很常见的关键字,但不知读者是否也能停下来思考一下。
- 由if-else,switch代替方案引起的思考
- 代替 if-else,switch-case 的几种方法
- switch代替if else实现学生成绩等级的判定,switch实现域的判定
- 使用map+函数指针代替switch和if-else的一个例子
- 用数组代替if-else和switch-case语句
- 由DevOps引起的思考
- state代替if-else
- if-else和switch的效率问题
- if else 和 switch的效率
- if else 和switch 的区别
- 反编译java的switch, if else 语句
- switch 和 if else的效率区别
- day3 if else 和switch的学习
- if else 与 switch case的区别:
- if else 和 switch 的区别
- switch和if else的效问题
- switch 与 if/else
- if()else + switch用法
- 关于纯java连接数据TCP/IP连接不成功的提示
- Bugly的使用
- LeetCode题解–137. Single Number II
- OpenGL坐标变换 平移,缩放与旋转
- unity编译时找不到AndroidSDK:Unable to list target platforms
- 由if-else,switch代替方案引起的思考
- 接收广播的两种方法
- golang通过zookeeper实现master选举
- 题目1016:火星A+B
- count(column) 和 count(*)和count(1)
- 希尔排序
- out of sync with file system
- js正则表达式语法
- iOS