引子
平時我是個反應非常慢的人。有多慢呢?大概是兩年前有次團隊內部開會時,我聽到同學說平時程式碼中用不到設計模式,我當時沒有回答。兩年後我終於反應過來了:“Are you kidding me?我每天都在用!”
應用場景
建造者模式
寫一個介面,入參是一大堆,什麼都有。這是長期積累下來的程式碼,引數都提供給外部用了。只能做加法,不能做減法。這時候介面就這樣了,內部能不能好看點呢?
可以啊,重構,留殼摳瓤啊!
這一堆引數可以封裝成一個有意義的類,再往下傳遞處理。這時候就用到了建造者模式,對引數進行封裝。構造一個靜態builder函式,將引數傳進去,返回是一個物件。
例子如下:
這是構造一個“人”的物件。builder函式建議放到“人”這個物件裡,因為這樣從領域上來說更合理更清晰。
@Data @Accessors(chain = true) public class Person { private String name; private int armCount=2;//胳膊數預設為2 private int legCount=2;//腿數預設為2 private Person(String name) { this.name = name; } public static Person builder(String name) { return new Person(name); } }
介面卡模式
大家現在用mysql都喜歡用mybatis-generator工具自動生成部分程式碼。裡面的物件一般稱為領域物件。在上層給使用者返回結果的時候一般不直接用。因為資訊太多了。比如資料庫中固定結構的欄位:建立時間、更新時間、是否為邏輯刪除列這些,更好的一個方式是對外不可見。這時候就要對領域物件和傳輸層物件之間做一個轉換,這時候用到介面卡模式。
下面是使用BeanUtils將物件之間做適配的例子:
private static QuotaResponse toQuotaResponse(Quota quota) { QuotaResponse quotaResponse = new QuotaResponse(); BeanUtils.copyProperties(quota, quotaResponse); return quotaResponse; }
觀察者模式
資料庫設計時常用的一種表結構設計方式是子母表。比如可以為“人”設計一張資料表。軍人、工程師、特工有各自不同的屬性,它們是“人”這張資料表的關聯子表。為了展示時候的效率,將這些子母表展開,另外做一張展示表。
在寫一個定時任務時,如果掃描到“人”的狀態狀態更新了。比如“人”的胳膊數變了,這時候可以通知這些展示表,狀態都更新了。
舉個例子:
因為九頭蛇在街頭橫行,見人就砍,出現了一些殘疾人。神盾局特工Fitz(菲茲)正在研製一種肢體再生技術,這個技術完成將會是包括人在內的所有動物的福音。因此,人類醫院和動物醫院都作為觀察者都訂閱了Fitz的專案狀態。一旦完成,這些醫院都會得到通知。
定義醫院作為觀察者的通用介面
public interface Observer { void update(boolean isFinish); }
Fitz開放了一個attach方法,任何單位都可以實現Observer介面後通過這個方法被加入通知列表,一旦完成,Fiz將通知所有觀察者:
public class Fitz { private List<Observer> observers = new ArrayList<Observer>(); public void attach(Observer observer) { observers.add(observer); } public void finish() { notifyAllObservers(); } public void notifyAllObservers() { for (Observer observer : observers) { observer.update(true); } } }
總結
代入思考,技術提升的關鍵
推薦閱讀
關於作者
一線開發十二年,有日本東京和美國矽谷研發經驗。有百餘項技術發明專利,目前任美團點評技術專家。有自己的技術公眾號「程式設計一生」。如果您在閱讀文章時有什麼疑問或者發現文章的錯誤,歡迎在公眾號裡給我留言。