1
Abstract: The main difference between process-oriented design and object-oriented design is whether to use lengthy if else judgments in the business logic layer.

This article is shared from the HUAWEI cloud community " from if-else-oriented programming to state-oriented programming, reducing code complexity ", author: breakDraw.

The main difference between process-oriented design and object-oriented design is whether to use lengthy if else judgments in the business logic layer. If you are still using if else extensively, of course, except for the interface presentation layer, even if you use a completely object-oriented language like Java/C#, it can only show that your thinking stays in the traditional process-oriented language.

need

There is a very classic digital verification scenario, the requirements are as follows:
image.png

Hard-written code with high complexity

At this time, if you write it directly, it is likely to write code that is prone to extremely high complexity, and it is also easy to miss and make mistakes.

Examples are as follows:

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;
    }
}

The complexity of this code is 21. It is directly failed in the first test of subject, and it is very easy to make mistakes. If you change it, you will be dizzy or missed.
image.png

§ State machine optimization

The picture is quoted from Leetcode's official problem solution, see the link:
https://leetcode-cn.com/problems/valid-number/solution/you-xiao-shu-zi-by-leetcode-solution-298l/
image.png

It can be seen that the verification process can form a state. When a specific character is encountered, it enters a specific state to judge, and only a limited state can be accessed after this state. Therefore, we can define N states, and each state defines X state change conditions and change states.

This relationship can be maintained by using multiple maps in java.

You can write the following code. Although the amount of code seems to be higher, the maintainability and complexity have become much stronger.

    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;
        }
    }

It can be seen that the complexity is only 8, and the complexity will not exceed the standard.
image.png

Click to follow, and learn about Huawei Cloud's fresh technology for the first time~


华为云开发者联盟
1.4k 声望1.8k 粉丝

生于云,长于云,让开发者成为决定性力量