java設(shè)計(jì)模式--七大原則詳解
設(shè)計(jì)模式
軟件設(shè)計(jì)模式(Design pattern),又稱(chēng)設(shè)計(jì)模式,是一套被反復(fù)使用、多數(shù)人知曉的、經(jīng)過(guò)分類(lèi)編目的、代碼設(shè)計(jì)經(jīng)驗(yàn)的總結(jié)。使用設(shè)計(jì)模式是為了可重用代碼、讓代碼更容易被他人理解、保證代碼可靠性、程序的重用性。
打個(gè)比方就像蓋大廈和小木屋,當(dāng)功能簡(jiǎn)單,函數(shù)和代碼少時(shí),我們能較輕松的直接上手;但如果是像大廈那樣,功能復(fù)雜,需求可能變化且代碼量大時(shí),我們就不能直接上手就來(lái),需要像建筑圖紙那樣提前規(guī)劃設(shè)計(jì),那設(shè)計(jì)模式就像軟件(程序)的建筑圖紙。
設(shè)計(jì)模式的目的是為了讓軟件(程序)具有更好的:
1.代碼重用性
相同功能的代碼,不用多次編寫(xiě),降低冗余
2.可讀性
編程規(guī)范性, 便于其他程序員的閱讀和理解
3.可擴(kuò)展性
當(dāng)需要增加新的功能時(shí),非常的方便,也稱(chēng)為可維護(hù)性
4.可靠性
當(dāng)我們?cè)黾有碌墓δ芎螅瑢?duì)原來(lái)的功能沒(méi)有影響
5.使程序呈現(xiàn)高內(nèi)聚,低耦合的特性
模塊內(nèi)部緊密,但模塊間依賴(lài)小,一者出錯(cuò)不影響他者
單一職責(zé)原則
單一職責(zé)原則(Single responsibility principle),即一個(gè)類(lèi)應(yīng)該只負(fù)責(zé)一項(xiàng)職責(zé)。如類(lèi)A負(fù)責(zé)兩個(gè)不同職責(zé):職責(zé)1,職責(zé)2。當(dāng)職責(zé)1需求變更而改變A時(shí),可能造成職責(zé)2執(zhí)行錯(cuò)誤,所以需要將類(lèi)A的粒度分解為A1、A2。
單一職責(zé)原則注意事項(xiàng)和細(xì)節(jié)
- 降低類(lèi)的復(fù)雜度,一個(gè)類(lèi)只負(fù)責(zé)一項(xiàng)職責(zé)。
- 提高類(lèi)的可讀性,可維護(hù)性
- 降低變更引起的風(fēng)險(xiǎn)
- 通常情況下,我們應(yīng)當(dāng)遵守單一職責(zé)原則,只有邏輯足夠簡(jiǎn)單,才可以在代碼級(jí)違反單一職責(zé)原則;只有類(lèi)中方法數(shù)量足夠少,可以在方法級(jí)別保持單一職責(zé)原則
接口隔離原則
接口隔離原則(Interface Segregation Principle),即客戶端不應(yīng)該依賴(lài)它不需要的接口,即一個(gè)類(lèi)對(duì)另一個(gè)類(lèi)的依賴(lài)應(yīng)該建立在最小的接口上。
比如:類(lèi)A通過(guò)接口 I I I依賴(lài)類(lèi)B,類(lèi)C通過(guò)接口 I I I依賴(lài)類(lèi)D,如果接口 I I I對(duì)于類(lèi)A和類(lèi)C來(lái)說(shuō)不是最小接口,那么類(lèi)B和類(lèi)D必須去實(shí)現(xiàn)他們不需要的方法。
按隔離原則應(yīng)當(dāng)這樣處理:將接口 I I I拆分為獨(dú)立的幾個(gè)接口,將類(lèi)分別與他們需要的接口建立依賴(lài)關(guān)系,也就是采用接口隔離原則。
依賴(lài)倒轉(zhuǎn)原則
依賴(lài)倒轉(zhuǎn)原則(Dependence Inversion Principle),依賴(lài)倒轉(zhuǎn)(倒置)的中心思想是面向接口編程,所謂“倒轉(zhuǎn)”是指抽象不應(yīng)該依賴(lài)細(xì)節(jié),而是細(xì)節(jié)應(yīng)該依賴(lài)抽象。也就是高層模塊不應(yīng)該依賴(lài)低層模塊,二者都應(yīng)該依賴(lài)其抽象。因?yàn)橄鄬?duì)于細(xì)節(jié)的多變性,抽象的東西要穩(wěn)定的多。
比如有個(gè)Person類(lèi),可以接受Email、QQ和微信的消息。如果都為其提供一個(gè)專(zhuān)門(mén)的方法,就會(huì)讓代碼非常的冗余:
可以引入一個(gè)IReceiver接口,讓Person類(lèi)依賴(lài)該接口。這樣QQ、微信和Email各自實(shí)現(xiàn)IReceiver里面的方法即可:
里氏替換原則
里氏替換原則(Liskov Substitution Principle)要求所有引用基類(lèi)的地方必須能透明地使用其子類(lèi)的對(duì)象。也就是在繼承關(guān)系中,子類(lèi)盡量不要重寫(xiě)父類(lèi)的方法。繼承實(shí)際上讓兩個(gè)類(lèi)耦合性增強(qiáng)了,特別是運(yùn)行多態(tài)比較頻繁的時(shí),整個(gè)繼承體系的復(fù)用性會(huì)比較差。比如一種極端情況:一個(gè)類(lèi)繼承了另一個(gè)類(lèi),但卻重寫(xiě)了所有方法,那么繼承的意義何在?說(shuō)好的復(fù)用呢?
解決方法是把原來(lái)的父類(lèi)和子類(lèi)都繼承一個(gè)更通俗的基類(lèi),在適當(dāng)?shù)那闆r下,可以通過(guò)聚合,組合,依賴(lài)等來(lái)代替。
開(kāi)閉原則
開(kāi)閉原則(Open Closed Principle)一個(gè)軟件實(shí)體如類(lèi),模塊和函數(shù)應(yīng)該對(duì)擴(kuò)展開(kāi)放(對(duì)提供方),對(duì)修改關(guān)閉(對(duì)使用方)。也就是當(dāng)軟件需要變化時(shí),盡量通過(guò)擴(kuò)展軟件實(shí)體的行為來(lái)實(shí)現(xiàn)變化,而不是通過(guò)修改已有的代碼來(lái)實(shí)現(xiàn)變化。用抽象構(gòu)建框架,用實(shí)現(xiàn)擴(kuò)展細(xì)節(jié)。開(kāi)閉原則是編程中最基礎(chǔ)、最重要的設(shè)計(jì)原則。編程中遵循其它原則,以及使用設(shè)計(jì)模式的目的就是遵循開(kāi)閉原則。
舉個(gè)違反開(kāi)閉原則的例子:
矩形Retangle和圓形Circle繼承了圖形類(lèi)Shape(提供方),畫(huà)圖類(lèi)GraphicEditor(使用方)會(huì)調(diào)用相關(guān)屬性。
但是如果再新增一個(gè)三角形,就要在使用方GraphicEditor新增對(duì)應(yīng)方法,修改地方較多,違背開(kāi)閉原則。
改進(jìn):把Shape做成抽象類(lèi)并提供抽象方法draw,讓子類(lèi)去實(shí)現(xiàn)即可。當(dāng)新增圖形種類(lèi)時(shí),只需讓新的圖形類(lèi)繼承Shape,并實(shí)現(xiàn)draw方法即可。使用方的代碼就不需要修改,滿足開(kāi)閉原則。
迪米特法則
迪米特法則(Demeter Principle)又叫最少知道原則,即一個(gè)類(lèi)對(duì)自己依賴(lài)的類(lèi)知道的越少越好,核心是降低類(lèi)之間的耦合。也就是說(shuō),對(duì)于被依賴(lài)的類(lèi)不管多么復(fù)雜,都盡量將邏輯封裝在類(lèi)的內(nèi)部。對(duì)外除了提供的public 方法,不對(duì)外泄露任何信息。避免與非直接朋友的耦合,只與直接的朋友通信,所謂的直接朋友是出現(xiàn)成員變量,方法參數(shù),方法返回值中的類(lèi)。而出現(xiàn)在局部變量中的類(lèi)不是直接的朋友。也就是說(shuō),陌生的類(lèi)最好不要以局部變量的形式出現(xiàn)在類(lèi)的內(nèi)部。
比如有學(xué)院?jiǎn)T工類(lèi)和學(xué)校員工類(lèi),然后各有一個(gè)管理類(lèi)有可以獲取其所有員工,學(xué)校員工管理類(lèi)有方法打印全部員工。
具體代碼:
void printAllEmployee(CollegeManager sub) { //獲取到學(xué)院?jiǎn)T工 List<CollegeEmployee> list1 = sub.getAllEmployee(); System.out.println("---學(xué)院?jiǎn)T工---"); for (CollegeEmployee e : list1) { System.out.println(e.getId()); } //獲取到學(xué)??偛繂T工 List<Employee> list2 = this.getAllEmployee(); System.out.println("---學(xué)校員工---"); for (Employee e : list2) { System.out.println(e.getId()); } }
分析SchoolManager類(lèi),發(fā)現(xiàn)Employee和CollegeManager都是它的直接朋友(出現(xiàn)在參數(shù)和返回值中),但CollegeEmployee不是直接朋友,是以局部變量的形式,違背了迪米特原則。
改進(jìn):避免依賴(lài)CollegeEmployee,封裝在CollegeManager中,對(duì)外提供public方法即可。
void printAllEmployee(CollegeManager sub) { sub.printEmployee(); //獲取到學(xué)??偛繂T工 List<Employee> list2 = this.getAllEmployee(); System.out.println("---學(xué)校員工---"); for (Employee e : list2) { System.out.println(e.getId()); } }
合成復(fù)用原則
合成復(fù)用原則(Composite Reuse Principle)就是是盡量使用合成/聚合的方式,而不是使用繼承。
總結(jié)
設(shè)計(jì)原則核心思想
針對(duì)接口編程,把應(yīng)用中可能需要變化的代碼和不需要變化的代碼分開(kāi)獨(dú)立。都是為了交互對(duì)象間解耦合而操心。
本篇文章就到這里了,希望能給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
mybatis中insert主鍵ID獲取和多參數(shù)傳遞的示例代碼
這篇文章主要介紹了mybatis中insert主鍵ID獲取和多參數(shù)傳遞的示例代碼,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03使用maven命令安裝jar包到本地倉(cāng)庫(kù)的方法步驟
這篇文章主要介紹了使用maven命令安裝jar包到本地倉(cāng)庫(kù)的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06淺析IDEA如何正確配置Gradle? GRADLE_USER_HOME 和 Gradle user home的區(qū)別
這篇文章主要介紹了IDEA如何正確配置Gradle? GRADLE_USER_HOME 和 Gradle user home的區(qū)別,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-08-08java實(shí)現(xiàn)MapReduce對(duì)文件進(jìn)行切分的示例代碼
本文主要介紹了java實(shí)現(xiàn)MapReduce對(duì)文件進(jìn)行切分的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01Java手把手必會(huì)的實(shí)例漢諾塔講解練習(xí)
漢諾塔,傳說(shuō)神在創(chuàng)造世界的時(shí)候做了三根金剛石柱子,并在一個(gè)教塔里留下了三根金剛石棒,第一根上面從上到下套著64個(gè)按從小到大排列的金盤(pán),神命令廟里的眾僧將它們一個(gè)個(gè)地從這根金剛石棒搬到另一根金剛石棒上,大盤(pán)不能放在小盤(pán)上。最后64個(gè)金盤(pán)仍然要按從小到大排列2021-09-09淺談java7增強(qiáng)的try語(yǔ)句關(guān)閉資源
下面小編就為大家?guī)?lái)一篇淺談java7增強(qiáng)的try語(yǔ)句關(guān)閉資源。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-06-06關(guān)于springboot-starter-undertow和tomcat的區(qū)別說(shuō)明
這篇文章主要介紹了關(guān)于springboot-starter-undertow和tomcat的區(qū)別說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03