單一職責(zé)原則簡稱 SRP,他想表達(dá)的就是字面意思,一個類只承擔(dān)一個職責(zé)。
有時候我們可以將一個復(fù)雜的接口拆成兩個不同的接口,這兩個接口承擔(dān)著不同的責(zé)任,這就是依賴了單一職責(zé)原則;它的定義就是:應(yīng)該有且僅有一個原因引起類的變更。
關(guān)于 職責(zé)
的定義很模糊,什么才是職責(zé)呢?不同的人有不同的解讀,所以該原則很難運(yùn)用,需要開發(fā)者的慧眼。
下面以大學(xué)學(xué)生工作管理程序為例介紹單一職責(zé)原則的應(yīng)用。
里式替換原則也叫 LSP 原則,沒錯就是你想的那個 lsp ??。
Liskov Substitution Principle
。繼承是非常優(yōu)秀的語言機(jī)制,它的優(yōu)點(diǎn)如下:
缺點(diǎn)是增加了代碼的耦合性,降低了代碼的靈活性。
但是從整體上看,繼承還是利大于弊的,我們想要將利最大化,就需要用到 里式替換
了。
里氏替換原則通俗來講就是:
依賴倒置原則的 3 個含義:
這里的抽象指的就是 接口或抽象類
,細(xì)節(jié)指的是 實現(xiàn)類
。
其核心思想是:要面向接口編程,不要面向?qū)崿F(xiàn)編程。
為什么面向接口呢?面向接口就是面向抽象,由于在軟件設(shè)計中,細(xì)節(jié)具有多變性,而 抽象層
則 相對穩(wěn)定 ,因此以抽象為基礎(chǔ)搭建起來的架構(gòu)要比以細(xì)節(jié)為基礎(chǔ)搭建起來的架構(gòu)要穩(wěn)定得多。
依賴倒置原則在 Java 中的表現(xiàn)是:
我們以一個例子來看一下依賴倒置原則的重要性:
現(xiàn)在有一個司機(jī),他想開一輛奔馳車。
代碼可以這樣寫:
司機(jī):
public class Driver() {public void drive(Benz benz) {benz.run();}}
奔馳車:
public class Benz() {public void run() {System.out.println("奔馳汽車開始運(yùn)行...");}}
主函數(shù):
public class Client() {public static void main() {Driver zhangSan = new Driver();Benz benz = new Benz();// 張三開奔馳車zhangSan.drive(benz);}}
這樣運(yùn)行起來,可以得到我們想要的結(jié)果,代碼沒有問題。
但是只有當(dāng)需求變更的時候才能真正的檢驗代碼的質(zhì)量。
現(xiàn)在題目要求司機(jī)開寶馬車,怎么改?
我們先創(chuàng)建出來寶馬車:
public class BMW() {public void run() {System.out.println("寶馬汽車開始運(yùn)行...");}}
寶馬車出來了,但是我們卻沒辦法讓張三將車開動起來,為什么?因為張三沒有開動寶馬車的方法啊。
此時我們發(fā)現(xiàn)我們的系統(tǒng)出現(xiàn)了問題:司機(jī)和奔馳車之間是緊耦合的關(guān)系,司機(jī)是實體類,奔馳車也是實體類,他們兩個發(fā)生了依賴關(guān)系,違背了我們說的依賴倒置原則。
那怎么修改呢?
既然是面向接口,那我們就創(chuàng)建兩個接口,讓抽象的接口互相依賴:
依賴的 3 種寫法
依賴是可以傳遞的,A 對象依賴 B 對象,B 又依賴 C,C 又依賴 D······,但是只要我們做到抽象依賴,即使是多層的依賴傳遞也不怕。
對象的依賴關(guān)系有三種方式來傳遞,分別是:
1、構(gòu)造函數(shù)傳遞依賴對象
public class Driver() {public void drive(Benz benz) {benz.run();}}
2、Setter 方法傳遞依賴對象
public interface IDriver {public void setCar(ICar car);public void drive();}
3、接口聲明依賴對象
在接口的方法中聲明依賴對象,也叫作接口注入。
public interface IDriver {public void driver(ICar car);}
那么我們在項目中怎么使用這個規(guī)則呢?可以從以下幾個方面入手:
我們可以得出一個通俗的規(guī)則:
接口隔離原則(Interface Segregation Principle,ISP)要求程序員盡量將臃腫龐大的接口拆分成更小的和更具體的接口,讓接口中只包含客戶感興趣的方法。
就是要讓接口中的方法盡可能的少而精。
同時注意,根據(jù)接口隔離原則拆分接口時,首先必須滿足 單一職責(zé)原則
,不能無限拆分。
例題:學(xué)生成績管理程序。
分析:學(xué)生成績管理程序一般包含插入成績、刪除成績、修改成績、計算總分、計算均分、打印成績信息、査詢成績信息等功能,如果將這些功能全部放到一個接口中顯然不太合理,正確的做法是將它們分別放在輸入模塊、統(tǒng)計模塊和打印模塊等 3 個模塊中,其類圖如圖所示。
迪米特法則(Law of Demeter,LoD)又叫作最少知識原則(Least Knowledge Principle,LKP)。
一個類應(yīng)該對自己需要耦合或調(diào)用的類知道的最少,你的內(nèi)部是如何復(fù)雜都和我沒有關(guān)系,那是你的事情,我就知道你提供那么多 public
方法,我就調(diào)用這么多,其他的我一概不關(guān)心。
先說一下什么是 朋友類 :
迪米特法則的目的就是低耦合,它包含 4 層含義:
1、只和朋友交流
也就是說符合迪米特法則的類中的方法,應(yīng)該不能出現(xiàn)非朋友類,不能和陌生人有交流。
2、朋友之間也是有距離的
人與人之間是有距離的,類與類之間也有距離,不能太過親密。
比如 A 類有 3 個方法,被 B 類的一個方法 m1
全部調(diào)用了,這樣一來就會有一個問題,當(dāng) A 類修改方法的名稱時,B 類也要修改 m1
方法,這就是耦合太緊了。
解決辦法就是將 m1
方法轉(zhuǎn)移到 A 類中去,讓 B 類調(diào)用 A 的 m1
方法,這樣就是高內(nèi)聚低耦合了。
同時 A 類中的 3 個方法可以設(shè)置成私有的,因為只有他自己調(diào)用,只需要將 m1
設(shè)置成 public
就可以了。
一個類公開的 public
屬性或方法越多,修改時涉及的面也就越大,迪米特法則要求類 羞澀
一點(diǎn),盡量內(nèi)斂。
3、是自己的就是自己的
如果一個方法放在本類中,既不增加類間關(guān)系,也對本類不產(chǎn)生負(fù)面影響,那就放置在本類中。
4、謹(jǐn)慎使用 Serializable
明星與經(jīng)紀(jì)人的關(guān)系實例。
分析:明星由于全身心投入藝術(shù),所以許多日常事務(wù)由經(jīng)紀(jì)人負(fù)責(zé)處理,如與粉絲的見面會,與媒體公司的業(yè)務(wù)洽淡等。這里的經(jīng)紀(jì)人是明星的朋友,而粉絲和媒體公司是陌生人,所以適合使用迪米特法則,其類圖如圖所示。
開閉原則是 Java 世界里最基礎(chǔ)的設(shè)計原則,它指導(dǎo)我們?nèi)绾谓⒁粋€穩(wěn)定的、靈活的系統(tǒng)。
他要求軟件實體應(yīng)該對擴(kuò)展開放,對修改關(guān)閉。
這里的軟件實體包括:
前面提到的幾個原則都是開閉原則的具體形態(tài),也就是說前五個原則就是指導(dǎo)設(shè)計的工具和方法,而開閉原則才是精神領(lǐng)袖。
開閉原則
在面向?qū)ο笤O(shè)計領(lǐng)域中的地位類似于牛頓第一定律在力學(xué)中的地位。
下面以 Windows 的桌面主題為例介紹開閉原則的應(yīng)用。
例題:Windows 的桌面主題設(shè)計。
分析:Windows 的主題是桌面背景圖片、窗口顏色和聲音等元素的組合。用戶可以根據(jù)自己的喜愛更換自己的桌面主題,也可以從網(wǎng)上下載新的主題。這些主題有共同的特點(diǎn),可以為其定義一個抽象類(Abstract Subject),而每個具體的主題(Specific Subject)是其子類。用戶窗體可以根據(jù)需要選擇或者增加新的主題,而不需要修改原代碼,所以它是滿足開閉原則的,其類圖如圖所示。
封裝
未來的變化。來源:https://www.icode9.com/content-4-793951.html
聯(lián)系客服