徹底弄懂類設計原則之 – 單一職責原則
類設計原則之 – 單一職責
類的設計原則之單一職責原則,是最常用的類的設計的原則之一
英文: SRP , Simple Responsibility Principle
中文:單一職責原則
這是面向對象類設計
中的第一個原則 ,也是看起來最簡單的一個原則,但是實際上遠遠沒有這麼簡單,很多人不一定真正理解了!
類設計,通俗的講不是怎麼去寫一個類更好,應該遵循什麼樣的原則設計類更好。
我們隨便找幾個網上的解釋:看看各位大師或者經典網站是怎麼解釋的。
百度百科:就一個類而言,應該僅有一個引起它變化的原因。應該只有一個職責。
說句實在話,我最開始也是對這句話似懂非懂,看的不是太明白,因為,引起一個類變化 的原因太多了,比如
- 給類增加一個方法是變化吧?
- 給類增加一個屬性是變化吧?
- 給類的方法增加一個函數是變化吧?
- ……
引起這些變化的原因太多了,如果每個原因都是一個職責,那麼SRP簡直就無法判斷了!
維基百科:(內容基本上和百度百科一致),通俗的講就是:一個類只做一件事
這個解釋更通俗易懂,也更符合中國人的理解。但是仔細想想,還是有幾個地方比較難理解:
什麼叫做 「一件事」 ?
舉個例子:
比如有一個學生管理類,這個類有 添加學生資訊
, 修改學生資訊
, 查詢學生資訊
, 刪除學生資訊
問題來了, 這是 4 件事 ? 還是 1 件事 ?
看起來好像是 4 件事, 但是稍有經驗的人都知道,這 4 件事都是由一個類來實現的,而不是設計 4 個類!
所以問題的關鍵在於:什麼是 「一件事」 ? 是每個功能一件事嗎?
其實答案就在我們自己身上, 因為只要我們工作,就無時無刻的在承擔著一定的職責
現在拋開面向對象,拋開軟體,拋開電腦,來看看我們自己的職責
- 比如我是一個程式設計師,我的職責是
寫程式
, 但寫程式
有很多事情,例如編碼
,單元測試
,系統測試
,bug修復
,開會
,寫文檔
等 - 比如我的老闆是一個管理者,他的職責是
管理程式設計師
,他也有很多工作,例如制訂計劃
,團隊建設
,開會
,協調
績效考評
等 - 比如我是一個快遞員,我的職責是送快遞,但是我也有很多事要做,例如
分包
,快遞
,收款
,開會
等
這些職責都不是我們自己定義的,而是公司或者部門或者組織,給我們安排工作的時候定義的。
也就是說,職責
是站在他人的角度上定義的,而不是我們自己定義的。
經過我們對職責
定義的分析,我們可以得出 2 個關於職責的重要結論
- 職責是站在他人的角度上定義的
- 職責不是一件事,而是很多事,但這些事都是和職責緊密結合的。
對應到面向對象設計領域,我們可以說一個類的職責應該如下定義:
- 類的職責是站在其它類的角度來定義的
- 類的職責包含多個相關功能
因此,SRP
可以翻譯為 一個類只負責一組相關的事
, 對應到程式碼中就是:一個類有多個方法,這些方法是相關的
有了這個定義,我們再來看看學生資訊管理類
, 很明顯,它具有的 4 個功能都是和 管理
相關的,按照 SRP
應該只設計一個學生資訊管理類
就可以了。
歡迎關注我們的 HelloWorld開發者社區, www.helloworld.net ,很好記的域名哦
SRP 的應用範圍
但是現實世界往往比理想更複雜,一個最典型的例子就是 辦公一體化
根據 SRP , 印表機可以設計成一個類,複印機可以設計成一個類,掃描儀可以設計成一個類,傳真機也可以設計成一個類
但偏偏就出了一個 辦公一體化
, 這個機器集成了 列印
, 複印
, 掃描
, 傳真
4 個職責 !
如果我們設計一個 辦公一體化
的類,怎麼也不可能設計出一個符合 SRP 的 辦公一體化的類
!
怎麼辦? 是 SRP 不正確 ? 還是我們永遠都不要設計一個 辦公一體化
的類 ?
其實 SRP 沒有錯, 辦公一體化
也應該設計, 但是不要用 SRP 原則來約束 辦公一體化
這樣的類!
也就是說, SRP 其實是有適用範圍的, SRP 只適合那些基礎類,而不適合基於基礎類構建複雜類的聚合類
在辦公一體化
的樣例中, 印表機
,複印機
, 掃描儀
,傳真機
都是基礎類,每個類都承擔一個職責
而 辦公一體化
是一個聚合類, 同時集成了4種功能!
細心的你可能發現了:SRP不能應用於聚合類, 那麼如何保證聚合類的設計品質呢?
換句話說,遇到這樣的情況,如何設計這樣的聚合類呢?
這個問題在 GoF 的 《設計模式》 一書中有詳細的答案,即優先使用對象組合 ,而不是類繼承。
類的單一原則就到這裡了,現小結一下:
- 類的單一原則(SRP):一個類只負責一組相關的事, 對應到程式碼中就是:
一個類有多個方法,這些方法是相關的
- 職責是站在他人的角度上定義的
- 類的職責包含多個相關功能
- SRP 只適合那些基礎類,而不適合基於基礎類構建複雜類的聚合類
- 對於複雜的聚合類,優先使用組合 ,而不是繼承
- 最後一條,歡迎關注我們的
HelloWorld開發者社區
, 網址:www.helloworld.net
,域名很好記哦
歡迎關注我們的下一篇文章,出講解更多的類設計的原則。