01. Java設(shè)計(jì)模式的設(shè)計(jì)原則
常見的7中面向?qū)ο笤O(shè)計(jì)原則
一、單一職責(zé)原則
一個(gè)類中負(fù)責(zé)一個(gè)功能領(lǐng)域中的相應(yīng)職責(zé)
二、開閉原則
軟件實(shí)體應(yīng)對擴(kuò)展開放,而對修改關(guān)閉
- 軟件越大,壽命越長;需要方便擴(kuò)展,擴(kuò)展時(shí)無需修改現(xiàn)有代碼。
- 抽象化設(shè)計(jì)<抽象類,接口>:開閉原則的關(guān)鍵,抽象層和實(shí)現(xiàn)層分離;如果需要改動系統(tǒng)的行為,只需要添加新的具體類實(shí)現(xiàn)新的業(yè)務(wù)功能,不修改已有的代碼從而擴(kuò)展系統(tǒng)的功能
不動源代碼,只需要動配置文件,也是符合開閉原則的軟件系統(tǒng)。
三、里氏代換原則
所有引用基類對象的地方都能夠透明地使用其子類對象【多態(tài)】
- 里氏代換原則是實(shí)現(xiàn)開閉原則的重要方式之一
- 在程序中盡量使用基類對對象進(jìn)行定義,在運(yùn)行時(shí)在確定其子類的類型。用子類對象替換父類對象(多態(tài))。
1). 注意
- 子類必須實(shí)現(xiàn)(抽象)父類/接口中所有的抽象方法。
- 盡量吧父類設(shè)計(jì)為抽象類或者接口。
- Java 會根據(jù)多態(tài)機(jī)制進(jìn)行編譯檢查,但是檢查是有局限性的。
四、依賴倒轉(zhuǎn)原則
抽象不應(yīng)該依賴于細(xì)節(jié),細(xì)節(jié)應(yīng)該依賴于抽象(針對接口編程,而不是針對實(shí)現(xiàn)編程)
在程序代碼中傳遞參數(shù)時(shí)或在關(guān)聯(lián)關(guān)系中,盡量引用層次高的抽象層類,即使用接口和抽象類進(jìn)行變量類型聲明、參數(shù)類型聲明、方法返回類型聲明,以及數(shù)據(jù)類型的轉(zhuǎn)換等,而不是用具體類類做這些事。為了確保該原則的引用,一個(gè)具體類應(yīng)當(dāng)只實(shí)現(xiàn)接口或抽象類中聲明過的方法,而不要給出多余的方法,否則將無法調(diào)用在子類中增加的新方法。
在程序中盡量使用抽象層進(jìn)行編程,而將具體類寫配置文件中,如果系統(tǒng)行為發(fā)生變化,只需要對抽象層進(jìn)行擴(kuò)展,修改配置文件,無需改變原有系統(tǒng)的源代碼,滿足開閉原則。
依賴倒轉(zhuǎn)中,當(dāng)一個(gè)對象與其他對象發(fā)生依賴關(guān)系。在該對象中聲明對應(yīng)的抽象類/接口。然后通過 構(gòu)造函數(shù)/setter/注解注入 的方式進(jìn)行注入。(DependencyInjection, DI)在程序運(yùn)行時(shí)確定執(zhí)行的對象。
1). 以下三個(gè)原則一般會同時(shí)出現(xiàn)
- 開閉原則 目標(biāo)(拓展開放,修改關(guān)閉)
- 里氏代換原則 基礎(chǔ)(多態(tài),基類可以,子類必須可以)
- 依賴倒轉(zhuǎn)原則 手段(DI)
五、接口隔離原則
使用多個(gè)專門的接口,而不是使用單一的總接口
- 接口盡量小,細(xì)化、但是不能太細(xì),否則不利于維護(hù)。
- 方法盡量少。
- 職責(zé)單一。
六、合成復(fù)用原則
盡量使用對象組合/聚合,而不是繼承來達(dá)到復(fù)用的目的
- 首先考慮組合/聚合的方式進(jìn)行設(shè)計(jì),這樣系統(tǒng)更加靈活,降低類之間的耦合度,一個(gè)類的變化對其他類造成的印象相對較少?!竞谙鋸?fù)用】
- 然后再考慮繼承(并謹(jǐn)慎使用),要嚴(yán)格遵循里氏代換原則;
1). 繼承可能造成的問題
- 破壞系統(tǒng)的封裝性。如果基類的內(nèi)部細(xì)節(jié)發(fā)生變化,子類的實(shí)現(xiàn)也不得不發(fā)生變化?!景紫鋸?fù)用】
- 從基類繼承而來的實(shí)現(xiàn)是靜態(tài)的,不可能在運(yùn)行時(shí)發(fā)生改變,沒有足夠的靈活性。
- 繼承只能在有限的環(huán)境下使用(類沒有被聲明為不能被繼承,就是沒有被final修飾的情況下才能使用繼承)
2). 組合/聚合 方式相對于 繼承 的優(yōu)勢
- 耦合度低,成員對象的變化對新對象的影響不大,可以在新對象中根據(jù)實(shí)際需要有選擇性地調(diào)用成員對象的操作
- 合成復(fù)用可以在運(yùn)行時(shí)動態(tài)進(jìn)行,新對象可以動態(tài)地引用與成員對象類型相同的其他對象。
3). 對象之間的關(guān)系
- is-a關(guān)系:關(guān)系密切,可以使用繼承。
- has-a關(guān)系:表示某一角色具有某一項(xiàng)責(zé)任,使用組合。
在使用組合的方式,同時(shí)利用里氏代換原則,依賴倒轉(zhuǎn)原則。
七、迪米特法則(最少知識法則)
一個(gè)軟件實(shí)體應(yīng)當(dāng)盡可能少地與其他實(shí)體發(fā)生相互作用,迪米特法則可以降低系統(tǒng)的耦合度,使類與類之間保持松散的耦合關(guān)系。
1). 特殊的幾種定義形式
- 不要和“陌生人”說話
- 只與對象的“直接朋友”通信,“直接朋友” 如下(其他情況的為“陌生人”)
- 當(dāng)前對象本身(this)
- 以參數(shù)形式傳入到當(dāng)前對象方法中的對象
- 當(dāng)前對象的成員對象
- 當(dāng)前成員對象(集合類型數(shù)據(jù))中的元素
- 當(dāng)前對象所創(chuàng)建的對象
【降低耦合的第三者】:在設(shè)計(jì)系統(tǒng)時(shí),應(yīng)該盡量減少對象之間的交互,如果兩個(gè)對象之間不必彼此直接通信,這兩個(gè)對象就不應(yīng)該發(fā)生任何直接的相互作用,如果其中一個(gè)對象需要調(diào)用另一個(gè)對象的某一個(gè)方法,可以通過【第三者】轉(zhuǎn)發(fā)這個(gè)調(diào)用,降低耦合度。
2). 注意:
- 在類的劃分上,盡量創(chuàng)建松耦合的類,耦合度越低,越利于復(fù)用,一個(gè)處在松耦合中的類一旦被修改,不會對關(guān)聯(lián)的類造成太大的波及;
- 在類的結(jié)構(gòu)設(shè)計(jì)上,每一個(gè)類都應(yīng)當(dāng)盡量降低其成員變量和成員函數(shù)的訪問權(quán)限。(private)
- 在類的設(shè)計(jì)上,只要有可能,一個(gè)類型應(yīng)當(dāng)設(shè)計(jì)成不變類;
- 在對其他類的引用上,一個(gè)對象對其他對象的引用應(yīng)當(dāng)降到最低。
附錄
一、最常見的7種面向?qū)ο笤O(shè)計(jì)原則排行榜
| 設(shè)計(jì)原則名稱 | 定義 | 使用頻率 |
|---|---|---|
| 開閉原則 (Open-Closed Principle, OCP) | 軟件實(shí)體應(yīng)對擴(kuò)展開放,而對修改關(guān)閉 | ★★★★★ |
| 里氏代換原則 (Liskov Substitution Principle, LSP) | 所有引用基類對象的地方能夠透明地使用其子類的對象 | ★★★★★ |
| 依賴倒轉(zhuǎn)原則 (Dependence Inversion Principle, DIP) | 抽象不應(yīng)該依賴于細(xì)節(jié),細(xì)節(jié)應(yīng)該依賴于抽象 | ★★★★★ |
| 單一職責(zé)原則 (Single Responsibility Principle, SRP) | 一個(gè)類只負(fù)責(zé)一個(gè)功能領(lǐng)域中的相應(yīng)職責(zé) | ★★★★☆ |
| 合成復(fù)用原則 (Composite Reuse Principle, CRP) | 盡量使用對象組合,而不是繼承來達(dá)到復(fù)用的目的 | ★★★★☆ |
| 迪米特法則 (Law of Demeter, LoD) | 一個(gè)軟件實(shí)體應(yīng)當(dāng)盡可能少地與其他實(shí)體發(fā)生相互作用 | ★★★☆☆ |
| 接口隔離原則 (Interface Segregation Principle, ISP) | 使用多個(gè)專門的接口,而不使用單一的總接口 | ★★☆☆☆ |
二、常見設(shè)計(jì)模式使用頻率排行榜
| 模式名稱 | 學(xué)習(xí)難度 | 使用頻率 |
|---|---|---|
| 抽象工廠模式(創(chuàng)建型) Abstract Factory Pattern | ★★★★☆ | ★★★★★ |
| 迭代器模式(行為型) Iterator Pattern | ★★★☆☆ | ★★★★★ |
| 觀察者模式(行為型) Observer Pattern | ★★★☆☆ | ★★★★★ |
| 工廠方法模式(創(chuàng)建型) Factory Method Pattern | ★★☆☆☆ | ★★★★★ |
| 外觀模式(結(jié)構(gòu)型) Fa?ade Pattern | ★☆☆☆☆ | ★★★★★ |
| 代理模式(結(jié)構(gòu)型) Proxy Pattern | ★★★☆☆ | ★★★★☆ |
| 組合模式(結(jié)構(gòu)型) Composite Pattern | ★★★☆☆ | ★★★★☆ |
| 命令模式(行為型) Command Pattern | ★★★☆☆ | ★★★★☆ |
| 適配器模式(結(jié)構(gòu)型) Adapter Pattern | ★★☆☆☆ | ★★★★☆ |
| 策略模式(行為型) Strategy Pattern | ★☆☆☆☆ | ★★★★☆ |
| 單例模式(創(chuàng)建型) Singleton Pattern | ★☆☆☆☆ | ★★★★☆ |
| 原型模式(創(chuàng)建型) Prototype Pattern | ★★★☆☆ | ★★★☆☆ |
| 橋接模式(結(jié)構(gòu)型) Bridge Pattern | ★★★☆☆ | ★★★☆☆ |
| 裝飾模式(結(jié)構(gòu)型) Decorator Pattern | ★★★☆☆ | ★★★☆☆ |
| 狀態(tài)模式(行為型) State Pattern | ★★★☆☆ | ★★★☆☆ |
| 簡單工廠模式(創(chuàng)建型) Simple Factory Pattern | ★★☆☆☆ | ★★★☆☆ |
| 模板方法模式(行為型) Template Method Pattern | ★★☆☆☆ | ★★★☆☆ |
| 建造者模式(創(chuàng)建型) Builder Pattern | ★★★★☆ | ★★☆☆☆ |
| 職責(zé)鏈模式(行為型) Chain of Responsibility Pattern | ★★★☆☆ | ★★☆☆☆ |
| 中介者模式(行為型) Mediator Pattern | ★★★☆☆ | ★★☆☆☆ |
| 備忘錄模式(行為型) Memento Pattern | ★★☆☆☆ | ★★☆☆☆ |
| 解釋器模式(行為型) Interpreter Pattern | ★★★★★ | ★☆☆☆☆ |
| 享元模式(結(jié)構(gòu)型) Flyweight Pattern | ★★★★☆ | ★☆☆☆☆ |
| 訪問者模式(行為型) Visitor Pattern | ★★★★☆ | ★☆☆☆☆ |