別再寫一摞if-else了!再寫開除!兩種設計模式帶你消滅它!
阿新 • • 發佈:2020-06-13
**程式碼潔癖狂們!看到一個類中有幾十個if-else是不是很抓狂?**
設計模式學了用不上嗎?面試的時候問你,你只能回答最簡單的單例模式,問你有沒有用過反射之類的高階特性,回答也是否嗎?
這次就讓設計模式(模板方法模式+工廠模式)和反射助你消滅if-else!
真的是開發中超超超超超超有用的乾貨啊!
# 那個坑貨
某日,碼農胖滾豬接到上級一個需求,這個需求牛逼了,一站式智慧報表查詢平臺,支援mysql、pgxl、tidb、hive、presto、mongo等眾多資料來源,想要啥資料都能通通給你查出來展示,對於業務人員資料分析有重大意義!
![image](https://yqfile.alicdn.com/20ed5c646f4b6055d98f6721ba75a34154d2b62d.png)
雖然各個資料來源的引數校驗、查詢引擎和查詢邏輯都不一樣,但是胖滾豬對這些框架都很熟悉,這個難不倒她,她只花了一天時間就都寫完了。
領導胖滾熊也對胖滾豬的效率表示了肯定。可是好景不長,第三天,領導閒著沒事,準備做一下code review,可把胖滾熊驚呆了,一個類裡面有近30個if-else程式碼,我滴個媽呀,這可讓程式碼潔癖狂崩潰了。
```
// 檢驗入參合法性
Boolean check = false;
if(DataSourceEnum.hive.equals(dataSource)){
check = checkHiveParams(params);
} else if(DataSourceEnum.tidb.equals(dataSource)){
check = checkTidbParams(params);
} else if(DataSourceEnum.mysql.equals(dataSource)){
check = checkMysqlParams(params);
} // else if ....... 省略pgxl、presto等
if(check){
if(DataSourceEnum.hive.equals(dataSource)){
list = queryHive(params);
} else if(DataSourceEnum.tidb.equals(dataSource)){
list = queryTidb(params);
} else if(DataSourceEnum.mysql.equals(dataSource)){
list = queryMysql(params);
} // else if ....... 省略pgxl、presto等
}
//記錄日誌
log.info("使用者={} 查詢資料來源={} 結果size={}",params.getUserName(),params.getDataSource(),list.size());
```
![image](https://yqfile.alicdn.com/702c397941b3ff589256c6d885156bd79f1fc5b2.png)
# 模板模式來救場
首先我們來分析下,不管是什麼資料來源,演算法結構(流程)都是一樣的,1、校驗引數合法性 2、查詢 3、記錄日誌。這不就是說模板一樣、只不過具體細節不一樣,沒錯吧?
讓我們來看看設計模式中模板方法模式的定義吧:
> 模板方法模式:定義一個操作中的演算法的框架,而將一些步驟延遲到子類中. 使得子類可以不改變一個演算法的結構即可重定義該演算法的某些特定步驟。通俗的講,就是將子類相同的方法, 都放到其抽象父類中。
我們這需求不就和模板方法模式差不多嗎?因此我們可以把模板抽到父類(抽象類)中。至於特定的步驟實現不一樣,這些特殊步驟,由子類去重寫就好了。
廢話不多說了,我們先把父類模板寫好吧,完全一樣的邏輯是記錄日誌,這步在模板寫死就好。至於檢驗引數和查詢,這兩個方法各不相同,因此需要置為抽象方法,由子類去重寫。
```
public abstract class AbstractDataSourcePr