软件设计原则(二)单一职责原则 -Single Responsibility Principle
SRP,Single Responsibility Principle:
There should never be more than one reason for a class to change.
應(yīng)該有且僅有一個原因引起類的變更。(如果類需要變更,那么只可能僅由某一個原因引起)
問題由來:
??????? 類T負(fù)責(zé)兩個不同的職責(zé):職責(zé)P1,職責(zé)P2。當(dāng)由于職責(zé)P1需求發(fā)生改變而需要修改類T時,有可能會導(dǎo)致原本運行正常的職責(zé)P2功能發(fā)生故障。
解決方案:
????????遵循單一職責(zé)原則。分別建立兩個類T1、T2,使T1完成職責(zé)P1功能,T2完成職責(zé)P2功能。這樣,當(dāng)修改類T1時,不會使職責(zé)P2發(fā)生故障風(fēng)險;同理,當(dāng)修改T2時,也不會使職責(zé)P1發(fā)生故障風(fēng)險。
示例:
???????如果一個接口包含了兩個職責(zé),并且這兩個職責(zé)的變化不互相影響,那么就可以考慮拆分成兩個接口。
???????方法的職責(zé)應(yīng)清晰、單一。一個method盡可能制作一件事情。changeUserInfo()可拆分為changeUserName()、changeUserAddr()....
??????? 說到單一職責(zé)原則,很多人都會不屑一顧。因為它太簡單了。稍有經(jīng)驗的程序員即使從來沒有讀過設(shè)計模式、從來沒有聽說過單一職責(zé)原則,在設(shè)計軟件時也會自覺的遵守這一重要原則,因為這是常識。在軟件編程中,誰也不希望因為修改了一個功能導(dǎo)致其他的功能發(fā)生故障。而避免出現(xiàn)這一問題的方法便是遵循單一職責(zé)原則。雖然單一職責(zé)原則如此簡單,并且被認(rèn)為是常識,但是即便是經(jīng)驗豐富的程序員寫出的程序,也會有違背這一原則的代碼存在。
??????? 為什么會出現(xiàn)這種現(xiàn)象呢?因為有職責(zé)擴(kuò)散。所謂職責(zé)擴(kuò)散,就是因為某種原因,職責(zé)P被分化為粒度更細(xì)的職責(zé)P1和P2。此時,按照SRP 應(yīng)該再新建一個類負(fù)責(zé)職責(zé)P2,但是這樣會修改花銷很大!除了改接口 還需要改客戶端代碼!所以一般就直接在原有類方法中增加判斷 支持職責(zé)P2;或者在原有類中新增一個方法來處理職責(zé)P2(做到了方法級別的SRP),
例如原有一個接口,模擬動物呼吸的場景:
程序上線后,發(fā)現(xiàn)問題了,并不是所有的動物都呼吸空氣的,比如魚就是呼吸水的。
修改一:修改時如果遵循單一職責(zé)原則,需要將Animal類細(xì)分為陸生動物類Terrestrial,水生動物Aquatic,代碼如下:
BUT,這樣修改花銷是很大的,除了將原來的類分解之外,還需要修改客戶端。
修改二:直接修改類Animal;雖然違背了單一職責(zé)原則,但花銷卻小的多
這種修改方式要簡單的多。但是卻存在著隱患:有一天需要將魚分為呼吸淡水的魚和呼吸海水的魚,則又需要修改Animal類的breathe方法,而對原有代碼的修改會對調(diào)用“豬”“牛”“羊”等相關(guān)功能帶來風(fēng)險,也許某一天你會發(fā)現(xiàn)程序運行的結(jié)果變?yōu)椤芭:粑绷恕?/span>
這種修改方式直接在代碼級別上違背了單一職責(zé)原則,雖然修改起來最簡單,但隱患卻是最大的。
修改三:
好處:
???????一個接口的修改只對相應(yīng)的實現(xiàn)類有影響,對其他接口無影響;有利于系統(tǒng)的可擴(kuò)展性、可維護(hù)性。
問題:
???????“職責(zé)”的粒度不好確定!
??????? 過分細(xì)分的職責(zé)也會人為地增加系統(tǒng)復(fù)雜性。
建議:
???????對于單一職責(zé)原則,建議 接口一定要做到單一職責(zé),類的設(shè)計盡量做到只有一個原因引起變化。
???????只有邏輯足夠簡單,才可以在代碼級別上違反單一職責(zé)原則;只有類中方法數(shù)量足夠少,才可以在方法級別上違反單一職責(zé)原則;
總結(jié)
以上是生活随笔為你收集整理的软件设计原则(二)单一职责原则 -Single Responsibility Principle的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 软件设计原则(一)开闭原则(Open-C
- 下一篇: 软件设计原则(三)里氏替换原则 -Lis