關於設計的個人看法
我們設計一個功能的時候,要考慮的無非是那些問題:可靠性,魯棒性,解耦性,擴充套件性,可讀性等等。
我們對程式碼和功能的設計過程,從面相物件的角度來講就是一個擬物或者擬人化的一個過程——我們先確定某個功能需要什麼樣的角色或者“零部件”參與,然後建立對應的類,指定類的角色職能;然後各個類各司其職;然後再考慮類的擴充套件性相關的問題,做出優化。
設計功能的第一步當然是明確需求,但是功能落地的重要過程我認為就是擬物擬人化的這個過程。
設計案例分析
現在我們有個需求,非同步模組——將要執行的資料放到後臺非同步去執行,使用場景有資料匯入匯出,資料庫間資料同步等。
現在我們進行擬物擬人化的過程(角色劃分)我將這個功能劃分成一下幾個角色
- 任務 指要處理的資料等
- 資源 這裡單指執行緒池
- 任務處理器 處理任務的具體邏輯。
- 管理器 負責排程執行緒,安排任務,將任務分發給各個處理器
功能設計到這,這個框架只能滿足使用要求,通用性不強;就是說,能用但是比較垃圾。為什麼這麼說,
首先,我們任務應該以什麼樣的形式獲取?又以什麼樣的形式去釋出一個一個任務?框架中未做說明,也沒有角色來幹這個事情,所以我們要在管理器中定義一個命令模式,這個命令就是任務,命令方法就是釋出任務,再在其內部使用模板方法模式固定一些演算法。再新增一個任務工廠來獲取和管理任務。
然後任務處理器這一端,任務處理邏輯肯定是使用者自己實現的,因此要具有適配性,這個適配性的支援,可以通過介面也可以通過註解,這都無所謂,所以我們還要新增一個任務處理器介面卡。
最後框架就成了這個樣子:
- 任務(命令)
- 任務工廠
- 任務處理器
- 任務處理器介面卡
- 管理器
- 資源(執行緒池)
OK,實話告訴你吧,這個框架和 springmvc
的原理是一個意思:request 對應任務、 dispatchServlet對應的是管理者,Maphandler 對應的是處理器介面卡,controller對應任務處理器, 任務工廠充當一個前端使用者角色傳送一個個請求。我這裡多了個命令傳送方的角色讓管理器充當了,你也可以在新增一個命令傳送器類。這個非同步框架流程就如下:
- 呼叫命令傳送器傳送一個命令(任務); 命令傳送器根據具體實現來決定這個命令是應該放入到記憶體中還是放入到資料庫裡還是直接執行。
- 任務工廠從資料庫,或者記憶體或者別的什麼地方讀取出任務,排根據任務優先順序序任務,然後將任務交給管理器。
- 管理器根據任務型別匹配到對應的任務處理器,交給任務處理器去處理
任務處理器的實現就像springmvc那樣,我們可以定義一個處理器介面,然後所有實現該介面的並注入到spring容器的物件都是處理器。也可以定義一個像@requestMaoing
那樣的註解,所有加上該註解的方法都會被適配成一個處理,實現起來也很容易。為了方便使用,我們還可以再對任務加一個監聽器,我們想釋出任務的時候只要丟擲一個事件即可,當然這只是附帶功能,非必須的功能。
關於程式碼可讀性的思考
一個好的設計模式還好說,一個使用糟糕的設計模式簡直是災難,作者就經歷過這種災難:設計模式用的莫名其妙,不暗2套路來,命名也無跡可尋,這樣的程式碼可讀性就很差。因為設計模式之間類關係本身就很複雜,在少一點註釋,真的很難去讀懂。那麼我們要怎麼讓一段程式碼能讓別人讀懂呢?第一就是加註釋,第二就是命名規範。下面我們就來說說設計模式的命名規範吧。
基本的一些命名:
- 模板方法模式的類一般以
template
結尾 - 工廠模式一般以
factory
結尾 - 代理模式一般以
proxy
結尾,代理方法一般命名為invoke()
- 執行命令的方法一般叫
execute()
,命令類一般以Command
結尾 - 觀察者模式中,監聽器一般以
listener
結尾 - 建造者一般以
builder
結尾 - 介面卡
Adapter
結尾
一些常用的“擬物” 結尾名詞
-
處理器/執行器
Resolver Processor Handler Executor Performer Runner
-
管理器控制器
Controller Manager Ordinator Leader Master
-
轉換器
Encoder/Decoder Transformer Converter
-
對映器
Mapper/Mapping
- 選擇器
Chooser
Selector
小結
對於許多原始碼而言,設計模式都是雜糅在一起的,許多類你不能片面的劃為哪一個設計模式,它可能在許多模式裡面都充當著角色。我們閱讀原始碼的時候要有通過命名去猜設計模式能力;同時我們也要有一定的聯想能力,能夠在實戰中聯想到相關原始碼,要學會 “抄作業” 。