如何去除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