共计 3353 个字符,预计需要花费 9 分钟才能阅读完成。
摘要: 面向过程设计和面向对象设计的次要区别是:是否在业务逻辑层应用简短的 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,不会复杂度超标。
点击关注,第一工夫理解华为云陈腐技术~