干掉if-else,多點套路,少點彎路!
你也許已經(jīng)看了無數(shù)使用 if-else 語句的教程,你可能也讀過不少使用 if-else 作為事實上的分支技術(shù)的編程書籍。
圖片來自 Pexels
它可能是也是你日常默認的編碼模式。但是,讓我們從今天起結(jié)束這種方法,用狀態(tài)對象代替 If-else。
請注意,如果你正在編寫的代碼需要根據(jù)當前狀態(tài)改變其實現(xiàn)的類,你需要改用這種方法。如果你的代碼不是處理對象的狀態(tài)變化,你需要選擇其他方法。
即使你已經(jīng)聽說過狀態(tài)模式,你可能也想了解如何在生產(chǎn)代碼中實現(xiàn)。
對于以前了解不多的人,下面有一段非常簡單的介紹。
對 if-else 增加任何新的條件,都會增加復(fù)雜性。應(yīng)用狀態(tài)模式(state pattern),你只需使用專門的狀態(tài)對象,代替 if-else 語句來改變一個對象的行為。
像下面這樣代碼的日子,已經(jīng)一去不復(fù)返了:
警告:PTSD 觸發(fā)器。另外,希望你能發(fā)現(xiàn)里面的邏輯錯誤(除了代碼整體一團糟)。
你以前肯定寫過更復(fù)雜的分支。我?guī)啄昵按_實寫過。
上面的分支邏輯雖然不是很復(fù)雜,但如果再添加新的條件,這個邏輯會更加混亂。
另外,如果你認為創(chuàng)建新的類,而不是簡單地使用分支語句聽起來很煩人,那就可以繼續(xù)看下面的實際代碼,它簡潔而優(yōu)雅。
更妙的是,它會讓你的代碼庫變得更 SOLID,除了 "D" 部分。
"好了,我相信 if-else 是邪惡的,現(xiàn)在請告訴我如何避免混亂的分支代碼"!
我們將看看我是如何在生產(chǎn)代碼中替換 if-else 分支的。這是一個假想的例子,但方法和我在大型客戶的代碼庫中使用的是一樣的。
讓我們創(chuàng)建一個非常簡單的 Booking 類,它有幾個狀態(tài)。它也會有兩個公共方法:Accept() 和 Cancel()。
我畫了一個圖,顯示了一個預(yù)訂可能處于的不同狀態(tài):
將分支邏輯從代碼中重構(gòu)出來,可以分為三步:
- 創(chuàng)建一個抽象的基本狀態(tài)類。
- 將每個狀態(tài)作為一個獨立的類來實現(xiàn),繼承于基本狀態(tài)。
- 讓 Booking 類有一個私有的或內(nèi)部的方法,把狀態(tài)基類作為參數(shù)。
演示時間
首先,我們需要一個用于繼承所有狀態(tài)的基礎(chǔ)狀態(tài)類。
請注意這個基類也有 Accept 和 Cancel 這兩個方法,雖然這里它們被標記為內(nèi)部方法。
此外,基礎(chǔ)狀態(tài)有一個特殊的 EnterState(Booking booking)方法。每當一個新的狀態(tài)被分配給預(yù)訂對象時,這個方法就會被調(diào)用。
其次,我們要為我們要表示的每一個狀態(tài)單獨做一個類。
請注意每個類是如何代表一個狀態(tài)的,就像上圖描述的那樣。另外,CancelledState 不會不允許預(yù)訂再轉(zhuǎn)換到一個新的狀態(tài)。這個類的設(shè)計與 Null Object Pattern 非常相似。
最后,再看看 Booking 類本身:
看到 Booking 類是如何簡單地將 Accept 和 Cancel 的實現(xiàn)委托給它的狀態(tài)對象的嗎?
這樣做可以讓我們?nèi)サ艉芏鄺l件邏輯,讓每個狀態(tài)只關(guān)注對自己重要的東西 -- 當前狀態(tài),以及也有可能將預(yù)訂轉(zhuǎn)換到新的狀態(tài)。
如何處理新的條件功能?
如果新功能通常會使用一些條件檢查來實現(xiàn),現(xiàn)在你可以直接創(chuàng)建一個新的狀態(tài)類。
就這么簡單。你將不再需要處理笨重的 if-else 語句。
如何將狀態(tài)對象持久化在數(shù)據(jù)庫中?
不需要。
當把一個對象保存到 SQL 或 NoSQL 數(shù)據(jù)庫時,狀態(tài)對象并不重要。只有知道對象的狀態(tài),以及如何將其映射到列才是重要的。
你可以將狀態(tài)映射到一個友好的類型名、一個枚舉或一個整型。只要你有某種方法將保存的值轉(zhuǎn)換回狀態(tài)對象,那就任何方法都行。
但為什么你還在使用 if?
是的,if 有時是必不可少的,尤其是作為防護語句(guard clause)使用時。if-else 組合才是讓人頭疼的可維護性的根本原因。
但是文中介紹的方法會帶來很多額外的類?
的確如此。正如我在另一篇文章中提到的,復(fù)雜性并不源于你擁有的類的數(shù)量,而是源于這些類所承擔的責任。
擁有許多專門的類,會讓你的代碼庫更易讀、更易維護,而且整體上更容易讓人喜歡。
作者:Nicklas Millard
編輯:陶家龍
出處:轉(zhuǎn)載自公眾號高可用架構(gòu)(ID:ArchNotes)