如何去除If,else,switch条件判断javascript
对于具备必定复杂逻辑的代码实现,避免不了出现if,else,switch等逻辑判断。当逻辑分支愈来愈多的时候,大大大加大了阅读的难度。这种状况,咱们该如何处理呢?
对同一个变量的不一样值做条件判断时,能够用switch语句与if语句,哪一个语句执行效率更高呢,答案是switch语句,尤为是判断的分支越多越明显。(具体测试的代码,小伙伴能够试一下)
public static void main(String[] args) { testIF("12"); testSwitch("12"); } public static void testIF(String arg) { long t1 = System.nanoTime(); if ("1".equals(arg)) { System.out.println(arg); } else if ("2".equals(arg)) { System.out.println(arg); } else if ("3".equals(arg)) { System.out.println(arg); } else if ("4".equals(arg)) { System.out.println(arg); } else if ("5".equals(arg)) { System.out.println(arg); } else if ("6".equals(arg)) { System.out.println(arg); } else if ("7".equals(arg)) { System.out.println(arg); } else if ("8".equals(arg)) { System.out.println(arg); } else if ("9".equals(arg)) { System.out.println(arg); } else if ("10".equals(arg)) { System.out.println(arg); } else if ("11".equals(arg)) { System.out.println(arg); } else if ("12".equals(arg)) { System.out.println(arg); } else if ("13".equals(arg)) { System.out.println(arg); } else if ("14".equals(arg)) { System.out.println(arg); } else { System.out.println(arg); } long t2 = System.nanoTime(); System.out.println("test if : " + (t2 - t1)); } public static void testSwitch(String arg) { long t1 = System.nanoTime(); switch (arg) { case "1": System.out.println(arg); break; case "2": System.out.println(arg); break; case "3": System.out.println(arg); break; case "4": System.out.println(arg); break; case "5": System.out.println(arg); break; case "6": System.out.println(arg); break; case "7": System.out.println(arg); break; case "8": System.out.println(arg); break; case "9": System.out.println(arg); break; case "10": System.out.println(arg); break; case "11": System.out.println(arg); break; case "12": System.out.println(arg); break; case "13": System.out.println(arg); break; case "14": System.out.println(arg); break; default: System.out.println(arg); break; } long t2 = System.nanoTime(); System.out.println("test switch: " + (t2 - t1)); }
最终现实结果
12
test if : 482713
12
test switch: 24870
复杂!复杂!代码圈复杂度高!
什么是代码圈复杂度?前端圈复杂度
1)概念:
- 用来衡量一个模块断定结构的复杂程度,数量上表现为独立现行路径条数,即合理的预防错误所需测试的最少路径条数,圈复杂度大说明程序代码可能质量低且难于测试和维护,根据经验,程序的可能错误和高的圈复杂度有着很大关系。
1)计算公式:
- 计算公式为:V(G)=e-n+2。其中,e表示控制流图中边的数量,n表示控制流图中节点的数量。 其实,圈复杂度的计算还有更直观的方法,由于圈复杂度所反映的是“断定条件”的数量,因此圈复杂度实际上就是等于断定节点的数量再加上1,也即控制流图的区域数,对应的计算公式为:V(G)=区域数=断定节点数+1。
- 对于多分支的CASE结构或IF-ELSE结构,统计断定节点的个数时须要特别注意一点,要求必须统计所有实际的断定节点数,也即每一个 ELSEIF语句,以及每一个CASE语句,都应该算为一个断定节点。断定节点在模块的控制流图中很容易被识别出来,因此,针对程序的控制流图计算圈复杂度 V(G)时,最好仍是采用第一个公式,也即V(G)=e-n+2;而针对模块的控制流图时,能够直接统计断定节点数,这样更为简单。
interface ILog { void log(); } class FileLog implements ILog { public void log() { } } class ConsoleLog implements ILog { public void log() { } } class NullObjectLog implements ILog { public void log() { } } public class LogFactory { static ILog Create(String str) { ILog log = new NullObjectLog(); if ("file".equals(str)) log = new FileLog(); if ("console".equals(str)) log = new ConsoleLog(); return log; } }
观察下面的一维数组的形式能够发现,定义了2个变量。
例如:int a[12],a[x]=y;
至关于函数 y=f(x) (在此例子中,x和y为均为int类型),因而就变成了咱们平时熟悉的普通的c函数。而函数通常经过数学表达式和逻辑判断的形式得出结果,而这样的结果通常的来讲有数学规律,例如像n!就很适合于使用函数实现。
而表驱动法的函数关系是人为定义的,若是采用函数,通常会出现不少的if、else判断。因此表驱动法适合于去实现“人造逻辑”的函数。
enum SexStatus { Female, Male } enum MaritalStatus { Single, Married } enum SmokingStatus { NonSmoking, Smoking } public double ComputeInsuranceCharge(SexStatus sexStatus, MaritalStatus maritalStatus, SmokingStatus smokingStatus, int age) { double rate = 1; if (sexStatus.equals(SexStatus.Female)) { if (maritalStatus.equals(MaritalStatus.Single)) { if (smokingStatus.equals(SmokingStatus.NonSmoking)) { if (age < 18) { rate = 40.00; } else if (age == 18) { rate = 42.50; } else if (age == 19) { rate = 45.00; } ... else if (age > 65) { rate = 150.00; } } else if (smokingStatus == SmokingStatus.Smoking) { if (age < 18) { rate = 44.00; } else if (age == 18) { rate = 47.00; } else if (age == 19) { rate = 50.00; } ... else if (age > 65) { rate = 200.00; } } } else if (maritalStatus == MaritalStatus.Married) { //...... } } return rate; }
可是仔细看一下代码,其实保险费率和性别、婚姻、是否抽烟、年龄这个几个因素有必定的关系,尤为年龄的变化区间是至关大,按照上述的写法,可想而知,代码的复杂会达到什么样子的程度。
这时候,确定有人会想不须要对每一个年龄进行判断,并且将保险费用放入年龄数组中,这样将极大地改进上述的代码。不过,若是把保险费用放入全部影响因素的数组而不只仅是年龄数组的话,将会使程序更简单,相似于能够设计一个费率表格,来下降代码的复杂度呢。java
Table<Integer, RateFactor, Double> rateTable = HashBasedTable.create(); enum RateFactor { MALE_SINGLE_NONSMOKING, MALE_SINGLE_SMOKING, MALE_MARRIED_NONSMOKING, MALE_MARRIED_SMOKING, FEMALE_SINGLE_NONSMOKING, FEMALE_SINGLE_SMOKING, FEMALE_MARRIED_NONSMOKING, FEMALE_MARRIED_SMOKING, } public double ComputeInsuranceCharge(RateFactor rateFactor, int age) { int ageFactor; if (age < 18) { ageFactor = 0; } else if (age > 65) { ageFactor = 65 - 17; } else { ageFactor = age - 17; } return rateTable.get(ageFactor, rateFactor); }
原先代码:设计模式
switch (something) { case 1: doX(); break; case 2: doY(); break; case 3: doN(); break; // And so on... }
重构后代码:数组
var cases = { 1: doX, 2: doY, 3: doN }; if (cases[something]) { cases[something](); }
关于表驱动法,仍是其余灵活的使用方法,能够参考《代码大全》函数
使用继承子类的多态,它们使用对象的间接性有效地摆脱了传统的状态判断。
使用继承子类多态的方式,一般对于某个具体对象,它的状态是不可改变的(在对象的生存周期中)。测试
public class Method { private int type; public static final int POST = 0; public static final int GET = 1; public static final int PUT = 2; public static final int DELETE = 3; public Method(int type) { this.type = type; } public String getMethod() throws RuntimeException { switch (type) { case POST: return "这是 POST 方法"; case GET: return "这是 GET 方法"; case PUT: return "这是 PUT 方法"; case DELETE: return "这是 DELETE 方法"; default: throw new RuntimeException("方法类型调用出错"); } } }
若是但愿对象在生存周期内,能够变化本身的状态,则能够选择state模式。
重构方法:这里抽象状态为一个接口MethodType,四种不一样的状态实现该接口。this