單一職責(zé)原則定義是:不要存在多于一個(gè)導(dǎo)致類變更的原因。通俗地說,即一個(gè)類只負(fù)責(zé)一項(xiàng)職責(zé)。
單一職責(zé)原則針對(duì)的問題
有一個(gè)類T負(fù)責(zé)兩個(gè)不同的職責(zé):職責(zé)P1和職責(zé)P2。當(dāng)因?yàn)槁氊?zé)P1的需求發(fā)生改變而需要修改類T的時(shí)候,有可能會(huì)導(dǎo)致原本運(yùn)行正常的職責(zé)P2功能發(fā)生故障。
單一職責(zé)原則的解決方案
遵循單一職責(zé)原則,分別建立兩個(gè)類T1、T2,使T1完成職責(zé)P1功能,T2完成職責(zé)P2功能。這樣,當(dāng)修改類T1的時(shí)候,不會(huì)使職責(zé)P2發(fā)生故障風(fēng)險(xiǎn)。同理,當(dāng)修改T2的時(shí)候,也不會(huì)使職責(zé)P1發(fā)生故障風(fēng)險(xiǎn)。
單一職責(zé)原則的認(rèn)識(shí)
說到單一職責(zé)原則,很多人都會(huì)不屑一顧,因?yàn)樗唵瘟?。稍有?jīng)驗(yàn)的程序員即使從來沒有讀過設(shè)計(jì)模式,從來沒有聽說過單一職責(zé)原則,在設(shè)計(jì)軟件的時(shí)候也會(huì)自覺遵守這個(gè)重要原則,因?yàn)檫@是一個(gè)常識(shí)。在軟件編程中,誰也不希望因?yàn)樾薷牧艘粋€(gè)功能導(dǎo)致其他的功能發(fā)生故障。而避免出現(xiàn)這一問題的方法便是遵循單一職責(zé)原則。雖然單一職責(zé)原則如此簡單,并且被認(rèn)為是常識(shí),但是即使是經(jīng)驗(yàn)豐富的程序員寫出的程序也會(huì)有違背這一設(shè)計(jì)原則的代碼存在。這是
職責(zé)擴(kuò)散導(dǎo)致的。所謂的職責(zé)擴(kuò)散,指的就是因?yàn)槟撤N原因,職責(zé)P1被分化為粒度更細(xì)的職責(zé)P1和P2。
比如說,類T只負(fù)責(zé)一個(gè)職責(zé)P,這樣設(shè)計(jì)是符合單一職責(zé)原則的。后來由于某種原因,或許是需求變更了,又或許是程序的設(shè)計(jì)者境界提高了,需要將職責(zé)P細(xì)分為粒度更細(xì)的職責(zé)P1和P2。這時(shí)候,如果要使程序遵循單一職責(zé)原則,就需要將類T也分解為兩個(gè)類T1和T2,分別去負(fù)責(zé)P1和P2兩個(gè)職責(zé)。但是在程序已經(jīng)寫好的情況下這樣做,十分浪費(fèi)時(shí)間和精力。所以,簡單地修改類T,用它來負(fù)責(zé)兩個(gè)職責(zé)是一個(gè)比較不錯(cuò)的選擇,雖然這樣做會(huì)有悖于單一職責(zé)原則。
適當(dāng)?shù)剡`背單一職責(zé)原則有時(shí)候反而能提高開發(fā)效率,因此設(shè)計(jì)原則還是要按照實(shí)際需求來選擇使用的。
單一職責(zé)原則的案例
用一個(gè)類來描述程序員編寫代碼這個(gè)場景。
public class AnimalTest { public static void main(String[] args) { Programmer
programmer= new Programmer(); programmer.program("靜靜"); // 靜靜使用IDEA編寫代碼。
programmer.program("標(biāo)標(biāo)");// 標(biāo)標(biāo)使用IDEA編寫代碼。 } } class Programmer { void
program(String programmer) { System.out.println(programmer+ "使用IDEA編寫代碼。"); } }
在工作中發(fā)現(xiàn),并不是所有的程序員都使用IDEA編寫代碼的,有的程序員喜歡用Eclipse,有的程序員喜歡用記事本。那么,這時(shí)候如果要遵循單一原則,就需要將Programmer類細(xì)分為野生程序員EclipseProgrammer和大佬程序員BossProgrammer。
public class AnimalTest { public static void main(String[] args) {
BossProgrammer bossProgrammer= new BossProgrammer(); bossProgrammer.program(
"飄飄");// 飄飄使用記事本編寫代碼。 EclipseProgrammer eclipseProgrammer = new
EclipseProgrammer(); eclipseProgrammer.program("毛毛"); // 毛毛使用Eclipse編寫代碼。 } }
class BossProgrammer { void program(String programmer) {
System.out.println(programmer+ "使用記事本編寫代碼。"); } } class EclipseProgrammer { void
program(String programmer) { System.out.println(programmer+ "使用Eclipse編寫代碼。");
} }
我們會(huì)發(fā)現(xiàn)這樣修改的花銷很大,因?yàn)樘幚硪獙⒃瓉淼念悾ū徽{(diào)用方)分解成多個(gè)類之外,還要修改調(diào)用方的代碼。這時(shí)候適當(dāng)?shù)剡`反單一職責(zé)原則,即在Programmer類中的program方法中使用條件分支的形式(使用程序員名硬編碼)就會(huì)簡單很多,只需要修改Programmer類(被調(diào)用方)即可,不需要修改調(diào)用方的代碼。當(dāng)然了,因?yàn)橛玫氖怯簿幋a,會(huì)導(dǎo)致很多時(shí)候條件判斷失敗,比如說程序員燦燦就不知道該用什么IDE去編寫代碼了。
上面的例子是個(gè)簡單的例子(只有一個(gè)方法),實(shí)際應(yīng)用中的類要比這復(fù)雜得多。一旦發(fā)生職責(zé)擴(kuò)散而需要修改類的時(shí)候,除非這個(gè)類本身非常簡單,否則還是遵循單一職責(zé)原則比較好。
單一職責(zé)原則的優(yōu)點(diǎn)
1.降低類的復(fù)雜度,一個(gè)類只負(fù)責(zé)一個(gè)職責(zé)。這樣寫出來的代碼邏輯肯定要比負(fù)責(zé)多項(xiàng)職責(zé)簡單得多。
2.提高類的可讀性,提高系統(tǒng)的可維護(hù)性。
3.降低變更引起的風(fēng)險(xiǎn)。變更是必然的,如果單一職責(zé)原則遵守得好,當(dāng)修改一個(gè)功能的時(shí)候可以顯著降低對(duì)其他功能的影響。
需要說明的一點(diǎn)是,單一職責(zé)原則不只是面向?qū)ο缶幊趟枷胨赜械?,只要是模塊化的程序設(shè)計(jì),都適用單一職責(zé)原則。比如說單一職責(zé)原則不僅僅適用于類,還適用于方法。
?
"做一個(gè)有溫度的人。"
熱門工具 換一換