我想談一談這個話題是因為我的上一篇博客有一些朋友回復說ifelse過多的分支可以使用switch或者責任鏈模式等等方式來優化確實這是一個小問題不過我們還是可以整理一下這個小問題的重構方式
為什麼要優化?
你沒有看錯這是要放在第一條談論的
有許多人會說疊起來一堆ifelse分支代碼就不優雅了可是怎樣去定義優雅的概念呢?再退一步說即便不優雅又有什麼問題?
對於這樣一段再普通不過的代碼
int code;
if(Nameequals(str))
code = ;
else if(Ageequals(str))
code = ;
else if(Addressequals(str))
code = ;
可以有好多種重構方式但是使用這樣的代碼雖然簡陋但在大多數情況下並不會影響什麼比如對可維護性沒有影響當然如果你發現其中確有不好的一面那就要考慮重構它換言之通常你首先要說出某段代碼的問題(比如你覺得這段代碼不符合開閉原則因為你希望保持這段代碼閉合穩定)那麼才去存在重構的必要而不要總是使用優雅和簡潔搪塞疑問幾乎所有的書上都說要寫出優雅的簡潔的代碼這本身無可厚非但是事物需要使用自己的判斷可不要被習慣性地洗了腦
在我前一家公司是典型的通訊和傳統軟件的公司代碼質量普遍不錯但是很多時候會看到許許多多不夠優雅的代碼——也許你覺得不夠簡潔美觀但是下代碼嚴謹清晰我覺得這就很好反之某一些精巧的設計可能會帶來可閱讀性和可理解性下降的問題
尋找代替分支判斷的方式
接下去我們再來考慮怎麼樣去重構優化過多的ifelse分支
程序邏輯最基本的組成就是分支判斷和循環而過多ifelse正是由於在某一個變化的點上有許多判斷條件和結果分支造成的所以最基本的解決辦法就是把多個判斷條件合成一個也就是把若干個分支合成一個
但是在大多數情況下條件判斷的分支都是無法合並的所以我們需要把這個變化點通過別的途徑封裝起來而不是采用ifelse
用一個Map可以做到ifelse的變化點使用Map的get方法來代替
Map typeCodeMap = new HashMap();
typeCodeMapput(Name );
typeCodeMapput(Age );
typeCodeMapput(Address );
int code = typeCodeget(type);
枚舉
public enum Codes {
Name() Age() Address();
public int code;
Codes(int code){
de = code;
}
}
//使用
int code = CodesvalueOf(de;
多態
ICode iCode = (ICode)ClassforName(comxxx + str)newInstance();
int code = iCodegetCode();
當然如果僅考慮從String轉向int這樣的轉換用這樣的方式來簡化分支判斷邏輯這個方式這個例子不是很恰當當然這樣的方式經常被用來做從字符串到具體對象的轉換
還有一些朋友說的這個模式那個模式來解決多ifelse的問題這些都是正確的當然本質上也無一例外基於多態來實現的所以我就不提及了這些都不錯至少比那些老說用switch來代替ifelse的有價值多了 :)
最後對於如此小的一個問題我要補充說明的一點是看不得大片ifelse和看不得大片new關鍵字一樣我覺得這是許多Java程序員的既有觀念或者說習慣甚至通病——這並不好Java最有價值的地方不是它的語義語法也不是它的虛擬機跨平台和有多高性能而在於它的社區它的無比豐富的類庫在於使用它的人可以從設計上和宏觀上去思考問題但是Java程序員也包括我在內很容易把這條路走得過於極端比如遍地的Factory比如漫山遍野的配置比如永遠也不會被復用的可復用代碼比如永遠也不會被擴展的可擴展代碼還比如從前到後由內到外的分層一層又一層相對於這些方面無止境的追求我們還是專注於要解決的問題多寫一些清晰可用的代碼吧
From:http://tw.wingwit.com/Article/program/Java/hx/201311/26892.html