1.單一職責(zé)原則
定義
單一職責(zé)原則(SRP:Single responsibility principle)又稱單一功能原則。它規(guī)定一個類應(yīng)該只有一個發(fā)生變化的原因。
特點
1 降低類的復(fù)雜性, 對類或接口的職責(zé)有清晰明確定義
2 提高可讀性
3 提高可維護性
4 降低變更引起的風(fēng)險, 接口改變只影響相應(yīng)的實現(xiàn)類, 不影響其他類
重點
接口一定要做到單一職責(zé);
類的單一職責(zé)比較難以實現(xiàn), 盡量做到只有一個原因引起變化;
一個方法盡可能做一件事, 能分解就分解, 分解到原子級別;

2.里氏替換原則
定義
所有 引用基類的地方 必須能 透明地使用其子類的對象;
通俗點講:只要 父類出現(xiàn)的地方子類就可以出現(xiàn), 替換為子類也不會產(chǎn)生任何錯誤, 使用者不需要知道父類還是子類;(策略模式)
需求
玩家玩射擊氣球游戲,他既能使用AK仿真槍,也可以使用步槍還可以使用手槍射擊氣球。
優(yōu)缺點
里氏替換原則核心是繼承,同樣它的優(yōu)缺點也是繼承的優(yōu)缺點
繼承的優(yōu)點
- 1 代碼共享 : 共享代碼, 子類都擁有父類的方法和屬性, 將 父類的代碼共享給了子類;
- 2 重用性 : 提高代碼的重用性, 子類重用父類的代碼;
- 3 子父類異同 : 子類形似父類, 異于父類, 父子都不同;
- 4 擴展性 : 提高代碼的可擴展性, 子類就可以為所欲為了, 子類可以隨意擴展父類;
- 5 開放性 : 提高產(chǎn)品或項目的開放性, 父類隨意擴展, 開放性隨之增加了;
繼承缺點 - 1 侵入性 : 繼承是侵入性的, 子類 強制繼承 父類的方法和屬性;
- 2 靈活性 : 降低代碼的靈活性, 子類必須擁有父類的屬性和方法, 子類收到了父類的約束, 這是從子類的角度講得;
- 3 耦合性 : 增強了耦合性, 父類的屬性和方法被修改時, 還需要顧及其子類, 可能會帶來大量的重構(gòu), 這是從父類的角度講的;
優(yōu)點:將子類單獨作為一個業(yè)務(wù)來使用, 會讓代碼間的耦合關(guān)系都復(fù)雜, 缺乏類替換標(biāo)準(zhǔn)
缺點 將子類當(dāng)做父類用, 抹殺了子類的個性;
重點
- 返回值: 父類方法返回值類型 F, 子類方法返回值類型 S, 里氏替換原則是 S 范圍必須小于 F;
- 重載: 父類 子類 方法參數(shù)類型或者數(shù)量不同, 如果要符合里氏替換要求的話, 子類參數(shù)必須 >= 父類參數(shù), 即不能讓子類自己定義的方法被調(diào)用;

3.依賴倒置原則
定義
細節(jié)依賴抽象 : 高層模塊不應(yīng)該依賴低層模塊,二者都應(yīng)該依賴其抽象;抽象不應(yīng)該依賴細節(jié);細節(jié)應(yīng)該依賴抽象。(依賴就是值引用)
抽象就是接口和抽象類
細節(jié)就是具體的實現(xiàn)類
問題由來
類A直接依賴類B,假如要將類A改為依賴類C,則必須通過修改類A的代碼來達成。這種場景下,類A一般是高層模塊,負責(zé)復(fù)雜的業(yè)務(wù)邏輯;類B和類C是低層模塊,負責(zé)基本的原子操作;假如修改類A,會給程序帶來不必要的風(fēng)險。
解決辦法
將類A修改為依賴接口I,類B和類C各自實現(xiàn)接口I,類A通過接口I間接與類B或者類C發(fā)生聯(lián)系,則會大大降低修改類A的幾率。
依賴倒置好處
減少類之間的耦合
提高系統(tǒng)穩(wěn)定性
降低并發(fā)風(fēng)險
提高代碼可讀性
依賴倒置注入實現(xiàn)
構(gòu)造函數(shù)依賴對象
注入方法 : 通過 構(gòu)造函數(shù)參數(shù) 聲明依賴對象, 即構(gòu)造函數(shù)注入;Setter 方法依賴對象
通過 Setter 函數(shù) 參數(shù) 聲明依賴對象, 即構(gòu)造函數(shù)注入;接口注入依賴對象
在接口方法的參數(shù)中聲明依賴對象, 即接口注入;
依賴倒置本質(zhì)
通過 抽象 即 接口或者抽象類, 使 各個類 和 模塊實現(xiàn)彼此獨立, 實現(xiàn)模塊間 松耦合;
注意點
盡量不要覆蓋方法, 如果方法在抽象類中已經(jīng)實現(xiàn), 子類不要覆蓋;
使用場景
依賴倒置在小項目中得有點很難體現(xiàn)出來, 是否采用依賴倒置原則影響不大;
項目越大, 需求改變越多, 采用依賴倒置原則設(shè)計的接口或抽象類 對 實現(xiàn)類的約束, 會大大減少維護成本
例子:媽媽講故事
4.接口隔離原則
定義
接口隔離定義 : 建立單一的接口, 功能盡量細化, 不要建立臃腫的接口;
- 不需要的接口 : 客戶端盡量不依賴其不需要的接口, 客戶端需要什么接口就提供什么接口, 剔除不需要的接口, 對接口進行細化, 保持接口方法最少;
- 最小接口 : 類間的依賴關(guān)系應(yīng)該建立在最小接口上, 細化接口;
單一職責(zé) 與 接口隔離 區(qū)別 :
- 單一原則 注重職責(zé), 注重業(yè)務(wù)邏輯上得劃分;
- 接口隔離 注重的是接口的方法盡量少
特點
- 接口盡量小
拆分接口 : 接口隔離的核心定義, 不出現(xiàn)臃腫的接口; - 接口高內(nèi)聚
高內(nèi)聚 : 提高接口, 類, 模塊的處理能力, 減少對外界交互;
具體方法 : 接口中盡量少公布public 方法, 對外公布的 public 方法越少, 變更的風(fēng)險就越小, 有利于后期的維護;
定制服務(wù)
起源 : 系統(tǒng)模塊間的耦合需要有相互訪問的接口, 這里就需要為各個 客戶端 的訪問提供定制的服務(wù)接口;
要求 : 只提供訪問者需要的方法, 不需要的就不提供;
接口隔離限度
- 粒度小 : 接口粒度越小, 系統(tǒng)越靈活, 但是同時使系統(tǒng)結(jié)構(gòu)復(fù)雜, 開發(fā)難度增加, 降低了系統(tǒng)的可維護性;
- 粒度大 : 靈活性降低, 無法提供定制服務(wù), 增大項目風(fēng)險;
原子接口劃分原則
- 接口模塊對應(yīng)關(guān)系 : 一個接口只服務(wù)于一個子模塊 或 業(yè)務(wù)邏輯;
- 方法壓縮 : 通過業(yè)務(wù)邏輯, 壓縮接口中得 public 方法, 減少接口的方法的數(shù)量;
- 修改適配 : 盡量去修改已經(jīng)污染的接口, 如果變更風(fēng)險較大, 采用適配器模式進行轉(zhuǎn)化處理;
例子:
Activity的OnclickListener和OnLongClickListener單獨分開。
5.迪米特法則
定義
最少知識原則, 一個對象應(yīng)該對其它對象有最少的了解, 即一個類對自己需要耦合或者調(diào)用的類知道的最少;
生活示例看代碼
朋友間必須保持距離
距離太近示例 : 朋友間不能無話不說, 無所不知, 類 A 與 B 耦合, B 將很多方法暴露給 A, 兩個類之間的的耦合關(guān)系非常牢固, 這明顯違反設(shè)計原則;
保持距離方法 : 將 類 B 暴露給 A 的方法封裝, 暴露的方法越少越好, 類 B 高內(nèi)聚, 與 A 低耦合;
設(shè)計方法 : 一個類的 public 方法越多, 修改時涉及的范圍也就越大, 變更引起的風(fēng)險也就越大, 在系統(tǒng)設(shè)計時要注意, 能用 private 就用private , 能用 protected 就用 protected, 能少用 public 就少用 public, 能加上 final 就加上 final;
優(yōu)缺點
- 優(yōu)點: 類間解耦, 弱耦合, 耦合降低, 復(fù)用率提高;
- 缺點、; 類間的耦合性太低, 會產(chǎn)生大量的中轉(zhuǎn)或跳轉(zhuǎn)類, 會導(dǎo)致系統(tǒng)的復(fù)雜性提高, 加大維護難度;
例子:
媽媽講故事,媽媽依賴書,后來,書需要修改,又依賴媽媽。兩個類互相耦合了。暴露給其他對象的方法,盡量簡單,對方只管使用就可以,不需要知道里面具體是怎么執(zhí)行的。如果對方都知道了,就不安全。
6.開閉原則
定義
軟件的實體類, 模塊, 函數(shù) 應(yīng)該對擴展開放, 對修改關(guān)閉; 即軟件實體應(yīng)該通過擴展實現(xiàn)變化, 不是通過修改已有的代碼實現(xiàn)變化;
優(yōu)點
利于測試 :
如果改變軟件內(nèi)容, 需要將所有的測試流程都執(zhí)行一遍, 如 單元測試, 功能測試, 集成測試等, 如果只是擴展, 只單獨測試擴展部分即可;提高復(fù)用性 :
所有邏輯都從原子邏輯組合, 原子邏輯粒度越小, 復(fù)用性越大; 這樣避免相同邏輯存在, 修改時需要修改多個此相同邏輯;提高可維護性 :
維護一個類最好的方式是 擴展一個類, 而不是修改一個類, 如果需要修改需要讀懂源碼才能修改, 擴展的話只需要了解即可, 直接繼承擴展;
總結(jié)
思想:
抽象 單一 最小化
方法:
面向接口編程
達到目標(biāo):
- 高擴展性
- 高內(nèi)聚
- 低耦合