1.單一職責(zé)原則
定義
單一職責(zé)原則(SRP:Single responsibility principle)又稱單一功能原則纠俭。它規(guī)定一個(gè)類應(yīng)該只有一個(gè)發(fā)生變化的原因。
特點(diǎn)
1 降低類的復(fù)雜性, 對(duì)類或接口的職責(zé)有清晰明確定義
2 提高可讀性
3 提高可維護(hù)性
4 降低變更引起的風(fēng)險(xiǎn), 接口改變只影響相應(yīng)的實(shí)現(xiàn)類, 不影響其他類
重點(diǎn)
接口一定要做到單一職責(zé);
類的單一職責(zé)比較難以實(shí)現(xiàn), 盡量做到只有一個(gè)原因引起變化;
一個(gè)方法盡可能做一件事, 能分解就分解, 分解到原子級(jí)別;
2.里氏替換原則
定義
所有 引用基類的地方 必須能 透明地使用其子類的對(duì)象;
通俗點(diǎn)講:只要 父類出現(xiàn)的地方子類就可以出現(xiàn), 替換為子類也不會(huì)產(chǎn)生任何錯(cuò)誤, 使用者不需要知道父類還是子類;(策略模式)
需求
玩家玩射擊氣球游戲饼丘,他既能使用AK仿真槍,也可以使用步槍還可以使用手槍射擊氣球辽话。
優(yōu)缺點(diǎn)
里氏替換原則核心是繼承肄鸽,同樣它的優(yōu)缺點(diǎn)也是繼承的優(yōu)缺點(diǎn)
繼承的優(yōu)點(diǎn)
- 1 代碼共享 : 共享代碼, 子類都擁有父類的方法和屬性, 將 父類的代碼共享給了子類;
- 2 重用性 : 提高代碼的重用性, 子類重用父類的代碼;
- 3 子父類異同 : 子類形似父類, 異于父類, 父子都不同;
- 4 擴(kuò)展性 : 提高代碼的可擴(kuò)展性, 子類就可以為所欲為了, 子類可以隨意擴(kuò)展父類;
- 5 開放性 : 提高產(chǎn)品或項(xiàng)目的開放性, 父類隨意擴(kuò)展, 開放性隨之增加了;
繼承缺點(diǎn) - 1 侵入性 : 繼承是侵入性的, 子類 強(qiáng)制繼承 父類的方法和屬性;
- 2 靈活性 : 降低代碼的靈活性, 子類必須擁有父類的屬性和方法, 子類收到了父類的約束, 這是從子類的角度講得;
- 3 耦合性 : 增強(qiáng)了耦合性, 父類的屬性和方法被修改時(shí), 還需要顧及其子類, 可能會(huì)帶來(lái)大量的重構(gòu), 這是從父類的角度講的;
優(yōu)點(diǎn):將子類單獨(dú)作為一個(gè)業(yè)務(wù)來(lái)使用, 會(huì)讓代碼間的耦合關(guān)系都復(fù)雜, 缺乏類替換標(biāo)準(zhǔn)
缺點(diǎn) 將子類當(dāng)做父類用, 抹殺了子類的個(gè)性;
重點(diǎn)
- 返回值: 父類方法返回值類型 F, 子類方法返回值類型 S, 里氏替換原則是 S 范圍必須小于 F;
- 重載: 父類 子類 方法參數(shù)類型或者數(shù)量不同, 如果要符合里氏替換要求的話, 子類參數(shù)必須 >= 父類參數(shù), 即不能讓子類自己定義的方法被調(diào)用;
3.依賴倒置原則
定義
細(xì)節(jié)依賴抽象 : 高層模塊不應(yīng)該依賴低層模塊,二者都應(yīng)該依賴其抽象油啤;抽象不應(yīng)該依賴細(xì)節(jié)贴捡;細(xì)節(jié)應(yīng)該依賴抽象。(依賴就是值引用)
抽象就是接口和抽象類
細(xì)節(jié)就是具體的實(shí)現(xiàn)類
問(wèn)題由來(lái)
類A直接依賴類B村砂,假如要將類A改為依賴類C烂斋,則必須通過(guò)修改類A的代碼來(lái)達(dá)成。這種場(chǎng)景下,類A一般是高層模塊汛骂,負(fù)責(zé)復(fù)雜的業(yè)務(wù)邏輯罕模;類B和類C是低層模塊,負(fù)責(zé)基本的原子操作帘瞭;假如修改類A淑掌,會(huì)給程序帶來(lái)不必要的風(fēng)險(xiǎn)。
解決辦法
將類A修改為依賴接口I蝶念,類B和類C各自實(shí)現(xiàn)接口I抛腕,類A通過(guò)接口I間接與類B或者類C發(fā)生聯(lián)系,則會(huì)大大降低修改類A的幾率媒殉。
依賴倒置好處
減少類之間的耦合
提高系統(tǒng)穩(wěn)定性
降低并發(fā)風(fēng)險(xiǎn)
提高代碼可讀性
依賴倒置注入實(shí)現(xiàn)
構(gòu)造函數(shù)依賴對(duì)象
注入方法 : 通過(guò) 構(gòu)造函數(shù)參數(shù) 聲明依賴對(duì)象, 即構(gòu)造函數(shù)注入;Setter 方法依賴對(duì)象
通過(guò) Setter 函數(shù) 參數(shù) 聲明依賴對(duì)象, 即構(gòu)造函數(shù)注入;接口注入依賴對(duì)象
在接口方法的參數(shù)中聲明依賴對(duì)象, 即接口注入;
依賴倒置本質(zhì)
通過(guò) 抽象 即 接口或者抽象類, 使 各個(gè)類 和 模塊實(shí)現(xiàn)彼此獨(dú)立, 實(shí)現(xiàn)模塊間 松耦合;
注意點(diǎn)
盡量不要覆蓋方法, 如果方法在抽象類中已經(jīng)實(shí)現(xiàn), 子類不要覆蓋;
使用場(chǎng)景
依賴倒置在小項(xiàng)目中得有點(diǎn)很難體現(xiàn)出來(lái), 是否采用依賴倒置原則影響不大;
項(xiàng)目越大, 需求改變?cè)蕉? 采用依賴倒置原則設(shè)計(jì)的接口或抽象類 對(duì) 實(shí)現(xiàn)類的約束, 會(huì)大大減少維護(hù)成本
例子:媽媽講故事
4.接口隔離原則
定義
接口隔離定義 : 建立單一的接口, 功能盡量細(xì)化, 不要建立臃腫的接口;
- 不需要的接口 : 客戶端盡量不依賴其不需要的接口, 客戶端需要什么接口就提供什么接口, 剔除不需要的接口, 對(duì)接口進(jìn)行細(xì)化, 保持接口方法最少;
- 最小接口 : 類間的依賴關(guān)系應(yīng)該建立在最小接口上, 細(xì)化接口;
單一職責(zé) 與 接口隔離 區(qū)別 :
- 單一原則 注重職責(zé), 注重業(yè)務(wù)邏輯上得劃分;
- 接口隔離 注重的是接口的方法盡量少
特點(diǎn)
- 接口盡量小
拆分接口 : 接口隔離的核心定義, 不出現(xiàn)臃腫的接口; - 接口高內(nèi)聚
高內(nèi)聚 : 提高接口, 類, 模塊的處理能力, 減少對(duì)外界交互;
具體方法 : 接口中盡量少公布public 方法, 對(duì)外公布的 public 方法越少, 變更的風(fēng)險(xiǎn)就越小, 有利于后期的維護(hù);
定制服務(wù)
起源 : 系統(tǒng)模塊間的耦合需要有相互訪問(wèn)的接口, 這里就需要為各個(gè) 客戶端 的訪問(wèn)提供定制的服務(wù)接口;
要求 : 只提供訪問(wèn)者需要的方法, 不需要的就不提供;
接口隔離限度
- 粒度小 : 接口粒度越小, 系統(tǒng)越靈活, 但是同時(shí)使系統(tǒng)結(jié)構(gòu)復(fù)雜, 開發(fā)難度增加, 降低了系統(tǒng)的可維護(hù)性;
- 粒度大 : 靈活性降低, 無(wú)法提供定制服務(wù), 增大項(xiàng)目風(fēng)險(xiǎn);
原子接口劃分原則
- 接口模塊對(duì)應(yīng)關(guān)系 : 一個(gè)接口只服務(wù)于一個(gè)子模塊 或 業(yè)務(wù)邏輯;
- 方法壓縮 : 通過(guò)業(yè)務(wù)邏輯, 壓縮接口中得 public 方法, 減少接口的方法的數(shù)量;
- 修改適配 : 盡量去修改已經(jīng)污染的接口, 如果變更風(fēng)險(xiǎn)較大, 采用適配器模式進(jìn)行轉(zhuǎn)化處理;
例子:
Activity的OnclickListener和OnLongClickListener單獨(dú)分開担敌。
5.迪米特法則
定義
最少知識(shí)原則, 一個(gè)對(duì)象應(yīng)該對(duì)其它對(duì)象有最少的了解, 即一個(gè)類對(duì)自己需要耦合或者調(diào)用的類知道的最少;
生活示例看代碼
朋友間必須保持距離
距離太近示例 : 朋友間不能無(wú)話不說(shuō), 無(wú)所不知, 類 A 與 B 耦合, B 將很多方法暴露給 A, 兩個(gè)類之間的的耦合關(guān)系非常牢固, 這明顯違反設(shè)計(jì)原則;
保持距離方法 : 將 類 B 暴露給 A 的方法封裝, 暴露的方法越少越好, 類 B 高內(nèi)聚, 與 A 低耦合;
設(shè)計(jì)方法 : 一個(gè)類的 public 方法越多, 修改時(shí)涉及的范圍也就越大, 變更引起的風(fēng)險(xiǎn)也就越大, 在系統(tǒng)設(shè)計(jì)時(shí)要注意, 能用 private 就用private , 能用 protected 就用 protected, 能少用 public 就少用 public, 能加上 final 就加上 final;
優(yōu)缺點(diǎn)
- 優(yōu)點(diǎn): 類間解耦, 弱耦合, 耦合降低, 復(fù)用率提高;
- 缺點(diǎn)、廷蓉; 類間的耦合性太低, 會(huì)產(chǎn)生大量的中轉(zhuǎn)或跳轉(zhuǎn)類, 會(huì)導(dǎo)致系統(tǒng)的復(fù)雜性提高, 加大維護(hù)難度;
例子:
媽媽講故事全封,媽媽依賴書,后來(lái)桃犬,書需要修改刹悴,又依賴媽媽。兩個(gè)類互相耦合了攒暇。暴露給其他對(duì)象的方法土匀,盡量簡(jiǎn)單,對(duì)方只管使用就可以形用,不需要知道里面具體是怎么執(zhí)行的就轧。如果對(duì)方都知道了,就不安全尾序。
6.開閉原則
定義
軟件的實(shí)體類, 模塊, 函數(shù) 應(yīng)該對(duì)擴(kuò)展開放, 對(duì)修改關(guān)閉; 即軟件實(shí)體應(yīng)該通過(guò)擴(kuò)展實(shí)現(xiàn)變化, 不是通過(guò)修改已有的代碼實(shí)現(xiàn)變化;
優(yōu)點(diǎn)
利于測(cè)試 :
如果改變軟件內(nèi)容, 需要將所有的測(cè)試流程都執(zhí)行一遍, 如 單元測(cè)試, 功能測(cè)試, 集成測(cè)試等, 如果只是擴(kuò)展, 只單獨(dú)測(cè)試擴(kuò)展部分即可;提高復(fù)用性 :
所有邏輯都從原子邏輯組合, 原子邏輯粒度越小, 復(fù)用性越大; 這樣避免相同邏輯存在, 修改時(shí)需要修改多個(gè)此相同邏輯;提高可維護(hù)性 :
維護(hù)一個(gè)類最好的方式是 擴(kuò)展一個(gè)類, 而不是修改一個(gè)類, 如果需要修改需要讀懂源碼才能修改, 擴(kuò)展的話只需要了解即可, 直接繼承擴(kuò)展;
總結(jié)
思想:
抽象 單一 最小化
方法:
面向接口編程
達(dá)到目標(biāo):
- 高擴(kuò)展性
- 高內(nèi)聚
- 低耦合