設計模式之六大設計原則之《一》魔性的單一職責原則
定義:單一職責原則,英文全稱Single Responsbility Property。怎樣的類設計才稱的上符合單一職責原則呢?一句話:應該有且僅有一個原因引起類的變更(There should never be more than one reason for a class to change)。這句話看起來文縐縐,但是等下結合例子就會發現,這句話可以貫穿單一職責原則的始終。
為什麼說單一職責原則是魔性的?因為類的職責實在是難以劃分,沒有嚴格的標準導致了沒有唯一的答案。所以當你想和某個人吵架時,只要去問他:“你設計的類符合SRP嗎”?保證你爭個300回合,酣暢淋漓卻不分勝負。
首先我們看看下面這個每個人都寫過的類:
看了一遍這個介面是不是覺得怪怪的?是不是覺得有些地方不對勁,和自己寫的有些差別?如果你說沒有啊,我平時就這麼寫的,那麼兄弟,你涼了。仔細看,我們發現這個使用者IUserInfo接口裡既有和屬性相關的方法如setUserId(),又有業務邏輯在裡面如changePassword()。屬性和邏輯沒有分開,這很糟糕,我們現在把屬性和業務邏輯分開來:
這樣是不是很清晰,IUserBo只和屬性相關,IUserBiz只和業務邏輯相關。這裡我們讓IUserInfo繼承了這兩個介面,當我們需要使用到其中一方時,我們需要做個轉換:
IUserInfo userInfo=new UserInfo(); IUserBo userBo=(IUserBo)userInfo;
事實上,我們更傾向於單獨使用這兩個介面:
這樣,兩個介面就完全符合單一職責原則了。是不是覺得太簡單了?如果這個時候是類,會不會還是這麼簡單呢?
假如小明要去購物Shopping,這個Shopping包含挑選商品(select)和付款(pay)兩部分,如果按照SRP考慮的話,挑選過程和方式是變化的,付款過程和方式也是不唯一的,那我們是否應該將Shopping類分解為兩個類:
如果把購物這個類細分,那我們就會考慮:付款類是否也需要細分?一分二,二分四,子子孫孫無窮盡也。生硬的按照單一職責原則會導致類數量的劇增,反而給維護帶來了負擔,增加了系統的複雜性。
所以這裡可以得出一個有效的結論:對於介面一定要做到單一職責原則,對於類要儘量做到單一職責原則。
SRP不僅對介面、類有效,對方法同樣有意義。在設計函式時,應該儘量讓一個函式處理一個問題,比如這個方法是用來修改密碼的,就不應該也可以修改地址。
如果我們在開發的過程中時刻考慮SRP,那麼以後受益的不僅是我們自己,還有我們的同事,領導,公司。
這裡我給出一個類,大家思考下是否符合SRP原則?我們在下一節分析。
注:dial():撥號方法 chat():通訊過程 hangup:結束通話方法