面向对象六大原则——单一职责原则
什么是單一職責(zé)原則(Single Responsibility Principle, SRP)
?在講解什么是單一職責(zé)原則之前,我們先說一個例子,吊一下口味:我們在做項(xiàng)目的時候,會接觸到用戶,機(jī)構(gòu),角色管理這些模塊,基本上使用的都是RBAC模型(Role-Based Access Control,基于角色的訪問控制, 通過分配和取消角色來完成用戶權(quán)限的授予和取消,使動作主體(用戶)與資源的行為(權(quán)限)分離)。現(xiàn)在假設(shè)這樣一種場景,我們把用戶管理,修改用戶信息,增加機(jī)構(gòu),增加角色等維護(hù)信息寫到一個接口中進(jìn)行管理,類圖如下:
分析上面的類圖我們會發(fā)現(xiàn),這樣的設(shè)計(jì)是非常不合理的,用戶的屬性和用戶的行為是兩種不同的業(yè)務(wù)模式,把它們都寫在一個類中顯然不行。我們應(yīng)該把用戶的信息抽取成一個BO(Business Object, 業(yè)務(wù)對象), 把行為抽取成一個Biz(Business Logic, 業(yè)務(wù)邏輯), 重新設(shè)計(jì)的類圖如下:
SRP在類或接口中的使用
?SRP的原話是:There should never be more than one reason for a class to change.翻譯過來其實(shí)也很好懂:應(yīng)該有且僅有一個原因引起類的變更。看下面的例子:
/** 上面的的類圖對應(yīng)的接口入下 */ public interface IPhone{//撥通電話public void dial(String phoneNumber);//通話public void chat(Object o);//掛斷電話public void hangup(); }在看到這個接口的時候,我們都會認(rèn)為這樣的設(shè)計(jì)是沒有問題的,撥通電話,通話,掛斷電話寫在同一個接口里面并沒有什么錯。但是,我們仔細(xì)分析,這個接口真的沒有問題嗎?單一職責(zé)原則要求一個接口或類只有一個原因引起變化,也就是說一個接口或一個類只有一個原則,它就只負(fù)責(zé)一件事。 但我們分析上面這個接口,卻發(fā)現(xiàn)它包含了兩個職責(zé):一個時協(xié)議管理,一個是數(shù)據(jù)傳送。dial()和hangup()兩個方法實(shí)現(xiàn)的是協(xié)議管理,分別是撥通電話和掛機(jī)。chat()實(shí)現(xiàn)的是數(shù)據(jù)傳送,把我們說的話轉(zhuǎn)換成模擬信號或數(shù)字信號傳遞給對方,然后再把對方傳遞過來的信號還原成我們聽得懂的語言。這里的協(xié)議接通和數(shù)據(jù)傳送的變化都會引起該接口或?qū)崿F(xiàn)類的變化。我們想一想,這兩個職責(zé)會相互影響嗎?不管是什么協(xié)議,協(xié)議接通只負(fù)責(zé)將電話接通就行,而數(shù)據(jù)傳輸只需要傳輸數(shù)據(jù),不必要去管協(xié)議是如何接通的。所以通過分析,IPhone接口包含了兩個職責(zé),而且這兩個職責(zé)的變化不互相影響,這就可以考慮分成兩個接口,類圖如下:
觀察上面的類圖,我們發(fā)現(xiàn)這樣的設(shè)計(jì)會比原來籠統(tǒng)的設(shè)計(jì)優(yōu)雅的多,現(xiàn)在的設(shè)計(jì)在職責(zé)上比原來更加分明,讓人一眼就能看出這個接口負(fù)責(zé)的是什么。也許有人會問,Phone這個類實(shí)現(xiàn)了兩個接口,又把兩個職責(zé)融合在了一個類中,那么是不是就有兩個原因引起了它的變化了呢?別忘了,我們是面向接口編程,我們對外公布的是接口(API),并非實(shí)現(xiàn)類,給你提供了模板,在接口層面已經(jīng)為你明確了職責(zé),那么具體的實(shí)現(xiàn)怎么弄就需要開發(fā)者去考慮了。
SRP也適用于方法
?其實(shí),單一職責(zé)原則不僅適用于類,接口,同樣適用于方法中。這要舉一個例子了,比如我們做項(xiàng)目的時候會遇到修改用戶信息這樣的功能模塊,我們一般的想法是將用戶的所有數(shù)據(jù)都接收過來,比如用戶名,信息,密碼,家庭地址等等,然后統(tǒng)一封裝到一個User對象中提交到數(shù)據(jù)庫,我們一般都是這么干的,就如下面這樣:
?其實(shí)這樣的方法是不可取的,因?yàn)槁氊?zé)不明確,方法不明確,你到底是要修改密碼,還是修改用戶名,還是修改地址,還是都要修改?這樣職責(zé)不明確的話在與其他項(xiàng)目成員溝通的時候會產(chǎn)生很多麻煩,正確的設(shè)計(jì)如下:
SRP的優(yōu)點(diǎn)
- 類的復(fù)雜性降低,對于實(shí)現(xiàn)什么職責(zé)都有清晰明確的定義。
- 可讀性提高。
- 可維護(hù)性提高。
- 變更引起的風(fēng)險(xiǎn)降低,一個接口的修改只對相應(yīng)的實(shí)現(xiàn)類有影響,對其他接口無影響,這對系統(tǒng)的擴(kuò)展性,維護(hù)性都有非常大的幫助。
參考書籍
- 《設(shè)計(jì)模式之禪》
總結(jié)
以上是生活随笔為你收集整理的面向对象六大原则——单一职责原则的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 观察者模式Observer
- 下一篇: 理解zookeeper选举机制