摘要:面向过程设计和面向对象设计的次要区别是:是否在业务逻辑层应用简短的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/probl...

能够看到校验的过程能够组成一个状态, 当遇到特定字符时,进入特定的状态去判断,并且该状态前面只能接入无限的状态。因而咱们能够定义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/E            OPE(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,不会复杂度超标。

点击关注,第一工夫理解华为云陈腐技术~