摘要:面向过程设计和面向对象设计的主要区别是:是否在业务逻辑层使用冗长的if else判断。

本文分享自华为云社区《从面向if-else编程升级为面向状态编程,减少代码复杂度》,作者:breakDraw。

面向过程设计和面向对象设计的主要区别是:是否在业务逻辑层使用冗长的if else判断。如果你还在大量使用if else,当然,界面表现层除外,即使你使用Java/C#这样完全面向对象的语言,也只能说明你的思维停留在传统的面向过程语言上。

需求

有一个非常经典的数字校验场景, 需求如下:

复杂度高的硬写代码

这时候如果直接硬写,大概率写出容易复杂度巨高的代码,还容易遗漏而出错。

例子如下:

 class Solution {public boolean isNumber(String s) {int sign = 1;int pointSign = 1;int eSign = 1;int numSign = -1;int i = 0;int n = s.length();while(i<n){if(s.charAt(i)>='0'&&s.charAt(i)<='9'){numSign = 1;sign = -1;}else if(s.charAt(i)=='+'||s.charAt(i)=='-'){if(sign>0){sign = -sign;}else{return false;}if(i>0&&s.charAt(i-1)=='.'){return false;}}else if(s.charAt(i)=='.'){//numSign = -1;if(pointSign>0){pointSign = -pointSign;}else{return false;}if(i>0&&(s.charAt(i-1)=='e'||s.charAt(i-1)=='E')){return false;}}else if(s.charAt(i)=='e'||s.charAt(i)=='E'){if(eSign<0||numSign<0){return false;}eSign = -1;sign = 1;numSign = -1;pointSign = -1;}else{return false;}i++;}return numSign>0;}}

这段代码的复杂度为 21, 放在科目一考试直接不及格了,而且非常容易出错,改着改着把自己改晕了,或者改漏了。

§ 状态机优化

图片引用自Leetcode官方题解,链接见:
https://leetcode-cn.com/problems/valid-number/solution/you-xiao-shu-zi-by-leetcode-solution-298l/

可以看到校验的过程可以组成一个状态, 当遇到特定字符时,进入特定的状态去判断,并且该状态后面只能接入有限的状态。因此我们可以定义N个状态,每个状态定义X个状态变化条件和变化状态。

在java中用多个map即可进行维护这种关系。

可以写出如下的代码, 虽然代码量看起来更高了,但是可维护性和复杂度变强不少。

 class Solution {public enum CharType {NUMBER,OP,POINT,E;public static CharType toCharType(Character c) {if (Character.isDigit(c)) {return NUMBER;} else if (c == '+' || c == '-') {return OP;} else if (c == '.') {return POINT;} else if (c =='e' || c == 'E') {return E;} else {return null;}}}public enum State {INIT(false),OP1(false),// 在.前面的数字BEFORE_POINT_NUMBER(true),// 前面没数字的点NO_BEFORE_NUMBER_POINT(false),// 前面有数字的点BEFORE_NUMBER_POINT(true),// 点后面的数字AFTER_POINT_NUMBER(true),// e/EOPE(false),// E后面的符号OP2(false),// e后面的数字AFTER_E_NUMBER(true);// 是否可在这个状态结束private boolean canEnd;State(boolean canEnd) {this.canEnd = canEnd;}public boolean isCanEnd() {return canEnd;}}public Map<State, Map<CharType, State>> transferMap = new HashMap<>() {{Map<CharType, State> map = new HashMap<>() {{put(CharType.OP, State.OP1);put(CharType.NUMBER, State.BEFORE_POINT_NUMBER);put(CharType.POINT, State.NO_BEFORE_NUMBER_POINT);}};put(State.INIT, map);map = new HashMap<>() {{put(CharType.POINT, State.NO_BEFORE_NUMBER_POINT);put(CharType.NUMBER, State.BEFORE_POINT_NUMBER);}};put(State.OP1, map);map = new HashMap<>() {{put(CharType.POINT, State.BEFORE_NUMBER_POINT);put(CharType.NUMBER, State.BEFORE_POINT_NUMBER);put(CharType.E, State.OPE);}};put(State.BEFORE_POINT_NUMBER, map);map = new HashMap<>() {{put(CharType.NUMBER, State.AFTER_POINT_NUMBER);}};put(State.NO_BEFORE_NUMBER_POINT, map);map = new HashMap<>() {{put(CharType.NUMBER, State.AFTER_POINT_NUMBER);put(CharType.E, State.OPE);}};put(State.BEFORE_NUMBER_POINT, map);map = new HashMap<>() {{put(CharType.E, State.OPE);put(CharType.NUMBER, State.AFTER_POINT_NUMBER);}};put(State.AFTER_POINT_NUMBER, map);map = new HashMap<>() {{put(CharType.OP, State.OP2);put(CharType.NUMBER, State.AFTER_E_NUMBER);}};put(State.OPE, map);map = new HashMap<>() {{put(CharType.NUMBER, State.AFTER_E_NUMBER);}};put(State.OP2, map);map = new HashMap<>() {{put(CharType.NUMBER, State.AFTER_E_NUMBER);}};put(State.AFTER_E_NUMBER, map);}};public boolean isNumber(String s) {State state = State.INIT;for (char c : s.toCharArray()) {Map<CharType, State> transMap = transferMap.get(state);CharType charType = CharType.toCharType(c);if (charType == null) {return false;}if (!transMap.containsKey(charType)) {return false;}// 状态变更state = transMap.get(charType);}return state.canEnd;}}

可以看到复杂度也只有8,不会复杂度超标。

点击关注,第一时间了解华为云新鲜技术~

为了减少代码复杂度,我将if-else升级为面向状态编程相关推荐

  1. 设计模式取舍之道:代码复杂度权衡

    目录标题 前言 正文 详细分析 单例模式(Singleton Pattern) 工厂方法模式(Factory Pattern) 抽象工厂模式 策略模式 享元模式 观察者模式(Observer Patt ...

  2. 用python内置函数算复杂度吗_Python减少代码量的两个内置函数

    Python减少代码量的两个内置函数 前言 Python中内置了几个非常好用的函数. 当你掌握了这几个函数的用法后,有些场景下,不用自己去实现多余的冗余代码编写,只需要调用这些函数,便能很简短的帮你实 ...

  3. 一名Android程序员如何减少代码中该死的-if-else-嵌套,怎么让代码更简洁?

    减少代码中该死的-if-else-嵌套,让代码更简洁! 写在前面 不知大家有没遇到过像"横放着的金字塔"一样的if else嵌套: if (true) {if (true) {if ...

  4. finally 嵌套_学习 Rust【2】减少代码嵌套

    结论先行:减少代码嵌套就是降低复杂度. 资源管理一向是编程中的重要任务.当一个函数要管理多个资源时,很容易出现代码嵌套层级太深的问题,尤其是调用系统或第三方 API 时. 以 C 语言代码为例,这里简 ...

  5. 用代码复杂度分析风险

    一些测试技术,比如边界值分析和结对测试,可以有效的帮助我们在尽量少的增加风险的同时,减少测试用例的数目.然而常见的问题在于产品的缺陷并不是 平均分布在代码里面的.在一些典型的软件项目中,总有一些组件比 ...

  6. 减少代码重复率的方法

    1.使用设计模式.设计模式的可以提高代码的复用率,减少代码的重复度. 2.使用类模板或者函数模板,所谓的泛型编程.

  7. 编写良好的代码:如何减少代码的认知负荷

    Bug 少,性能好,容易修改.好的代码影响深远,而且它可能是产生 10 倍工作效率的开发者的主要原因.尽管好代码十分重要,但开发新手却不得要领.关于这一主题的技巧多而冗杂,让新手们如何记得住?&quo ...

  8. WPF INotifyPropertyChanged 通过特性减少代码量

    在很多地方需要用上INotifyPropertyChanged的接口,MVVM模式,List等集合都会用到. 通常我们使用 protected void OnChange(PropertyChange ...

  9. [简单题]换一个思维,代码简洁度就完全变了(Python实现)

    题目名字: Human readable duration format 原题链接: https://www.codewars.com/kata/human-readable-duration-for ...

最新文章

  1. 新手也能看懂的监控报警系统架构设计
  2. 推荐一些视觉SLAM的深度学习方法(上)
  3. GitHub发布重大更新,关系到所有程序员!
  4. 【VC基础】1、特性和分类
  5. python怎么把cpu占满_如何增加python CPU使用率
  6. 怎么控制latex插图的位置_如何在报告OR论文中画出漂亮的插图?
  7. cors解决ajax跨域
  8. 英语口语(5月17)
  9. linux拷贝文件夹到另一台机器,linux肿么一个文件拷贝到另一个文件夹
  10. ubuntu 下安装和配置selenium
  11. 突发!5G 标准推迟三个月
  12. 嵌套RecyclerView左右滑动替代自定义view
  13. 心电电路算法滤波_简述心电信号采集原理及电路设计
  14. 菲克扩散(第一)定律【Fick's (First) Law of Binary Diffussion】
  15. ddpush java_DDPush-任意门消息推送-开源推送服务器-推送-消息推送-信息推送-物联网推送...
  16. [项目管理-29]:SMART项目计划制定与PDCA闭环监控,珠联璧合,双剑合一。
  17. replay attacker
  18. 第07章 文本信息提取
  19. J-Link V9驱动
  20. 【免费赠送源码】Springboot剧本杀交流分享平台1p7vg计算机毕业设计-课程设计-期末作业-毕设程序代做

热门文章

  1. todo项目开发_Facebook的TODO项目,巴西的Coursera,Drupal等
  2. 用开源代码如何建立网站_建立开源社区时要考虑的6件事
  3. 开源项目参与_通过更好的文档吸引更多的项目参与人
  4. (49)移动端开发之流式布局(百分比布局)
  5. vue-router路由详细笔记
  6. Highcharts x轴为时间时,设置plotBands
  7. 微信小程序网络通信(一)
  8. Bootstrap CSS 编码规范之属性声明顺序
  9. 计算机f8键的功能,详解:XP系统修改启动时F8键有哪些功能?
  10. 永远不要去依赖别人_心理学:永远不要穿别人剩下的旧衣服,这三点原因读来让人愧疚...