設計模式總篇:從爲何須要原則到實際落地(附知識圖譜)

聊聊爲何須要原則

咱們全部人都看過科幻電影,都看到過將來場景中人類和機器人和平相處的場景java

爲了讓擁有自主智能的機器人不失控,人類爲機器人制定了三大定律:git

  • <font color="red">第必定律:機器人不得傷害人類個體,或者目擊人類個體將遭受危險而袖手無論</font>
  • <font color="red">第二定律:機器人必須服從人給予它的命令,當該命令與第必定律衝突時例外</font>
  • <font color="red">第三定律:機器人在不違反第1、第二定律的狀況下要儘量保護本身的生存</font>

固然有時也會出現下面的狀況,機器人和人類開始互爲陣營,各自爲敵github

可是各自爲敵的狀況出現,通常都是機器人覺醒了自我意識,再也不遵照三大定律編程

從邏輯學來講,若是機器人徹底遵照三大定律及其衍生的條約,那麼機器人就能夠和人類和平相處,固然也會有意外發生。設計模式

寫代碼爲何須要設計原則

和機器人的三大定律相仿,幾十年的編程經驗,讓幾代人總結出來了一些代碼設計上的定律,這就是設計模式的七大原則數組

咱們遵循七大原則,必定會寫出最完美的代碼嗎?ide

答案固然是不必定,畢竟沒有人能保證本身能夠徹底遵循七大原則,同時我的的編程能力也會起到決定性因素。post

那咱們爲何還要遵照?性能

我本身想到的一句名言(之後或許能夠成爲名言~)學習

向着最好的方向去努力,總不會是最差的結果。

七大原則詳解

開閉原則 ★★★★★

軟件實體對擴展是開放的,但對修改是關閉的,即在不修改一個軟件實體的基礎上去擴展其功能

例如:

以策略模式爲例,當咱們新增一種策略的時候,只須要實現策略頂層接口,在調用的時指向新的策略便可

針對這一條原則,在實現難度上要比單一職責更難,在編碼期間,咱們須要充分考慮將來的拓展性,規範接口,依賴抽象,這樣才能在須要拓展的時候,很是方便的實現其效果

最佳實踐案例:【一塊兒學系列】之模板方法:寫SSO我只要5分鐘

說明:在接入第三方SSO時,若是須要新增接入方,基於文中的案例,只需實現固定接口,便可優雅的實現相應需求

依賴倒置原則 ★★★★★

要針對抽象層編程,而不要針對具體類編程

例如:

以適配器模式爲例,將一個類的接口轉換成客戶但願的另一個接口,以此實現的前提即是代碼中所依賴的都是抽象的,由於只有依賴抽象,才能在代碼運行期間改變其實體,利用多態實現須要的效果

針對該條原則,其實有必定編程經驗的人必定會在無形中注意到,並且瞭解設計模式的話,會發現全部涉及接口和實現的設計模式都會聽從這一條原則

最佳實踐案例:【一塊兒學系列】之模板方法:寫SSO我只要5分鐘

說明:和上一條原則的側重點不一樣,在SSO中必然有其固定的流程,如登陸-獲取Token-獲取用戶信息-解析-退出等等,在代碼的編寫階段,須要咱們定義出接口/抽象類,而後依賴於抽象層,最終改變具體類,以此達到無縫切換的效果

合成複用原則 ★★★★☆

總結一句話就是:多用組合,少用繼承

例如:

以單例模式和代理模式爲例,它們都是該模式的最佳實踐者,單例模式是把不一樣的策略接口經過組合的方式嵌入到Context類中,如代碼所示:

public abstract class Duck {
    /**
     * 飛行行爲是動態的,可能會變的,所以抽成多個接口的組合,而不是讓Duck類繼承
     */
    FlyBehavior flyBehavior;

    /**
     * 每一個鴨子的叫聲不一樣,抽象成接口
     */
    QuackBehavior quackBehavior;
}

同理,代理模式也是如此,這裏就考慮到一個問題,爲何要多用組合而非繼承?

其實仍是Java中單繼承引起的問題,同時繼承的語義過於苛刻,所以更多的時候建議善用組合

最佳實踐案例:【一塊兒學系列】之策略模式:好多鴨子啊

說明:策略模式就是合成複用原則的最佳實踐者,沒有之一

單一職責原則 ★★★★☆

類的職責要單一,不能將太多的職責放在一個類中

例如:

在代碼設計中某種場景可能存在多種不一樣的狀態,極可能就把代碼混在一塊兒了,這時咱們利用狀態模式進行設計,把各類狀態對應的實現細節都用類的級別單獨劃分,即體現了單一職則原則

針對這一條原則,其實絕大多數人在設計之初都會考慮到,但問題就在於隨着工做中人員職責的交叉,頗有可能會破壞他人設計的最初目的,爲了方便,讓一個類擁有五花八門的功能

最佳實踐案例:【一塊兒學系列】之狀態模式:你聽過「流程」模式嗎?

說明:在狀態模式中,每一種狀態的處理都是獨立的一個類,每一個類只須要處理自身的核心邏輯,完美體現了單一職責原則

里氏代換原則 ★★★★☆

在軟件系統中,一個能夠接受基類對象的地方必然能夠接受一個子類對象

當使用繼承時,遵循里氏替換原則。類B繼承類A時,除添加新的方法完成新增功能外,儘可能不要重寫父類A的方法,也儘可能不要重載父類A的方法

繼承包含這樣一層含義:父類中凡是已經實現好的方法(相對於抽象方法而言),其實是在設定一系列的規範和契約,雖然它不強制要求全部的子類必須聽從這些契約,可是若是子類對這些非抽象方法任意修改,就會對整個繼承體系形成破壞。而里氏替換原則就是表達了這一層含義

例如:

咱們都用過ArrayList,有誰看過 forEach方法的源碼?

// ArrayList 的父級接口 Iterable  定義的默認方法
default void forEach(Consumer<? super T> action) {
    Objects.requireNonNull(action);
    for (T t : this) {
        action.accept(t);
    }
}

ArrayList重寫的方法:

@Override
public void forEach(Consumer<? super E> action) {
    Objects.requireNonNull(action);
    final int expectedModCount = modCount;
    @SuppressWarnings("unchecked")
    final E[] elementData = (E[]) this.elementData;
    final int size = this.size;
    for (int i=0; modCount == expectedModCount && i < size; i++) {
        action.accept(elementData[i]);
    }
    if (modCount != expectedModCount) {
        throw new ConcurrentModificationException();
    }
}

咱們看到,ArrayList的重寫只是針對數組這種結構優化了性能,其目的性和Iterable接口中的徹底一致,所以這種方式的重寫不會引發任何問題,反而能夠提升效率,咱們須要學習這樣的方式

迪米特原則 ★★★☆☆

一個對象應該對其餘對象保持最少的瞭解,又名:最少知道原則

例如:

在代碼設計場景中,某一個類的調用都會固定使用三個方法,是否能夠考慮把三個方法抽取出來,提供一個公共的對外方法?這種思路就是外觀模式,外觀模式也是迪米特原則的最佳實踐

最佳實踐案例:【一塊兒學系列】之適配器模式:還有外觀模式呢

說明:利用外觀模式構建統一的對外方法,屏蔽其內部實現,這樣一旦內部實現須要更改,徹底不會影響調用方,你Get了嗎?

接口隔離原則 ★★☆☆☆

使用多個專門的接口來取代一個統一的接口

這個模式其實也很好理解,好比咱們定義了接口A,接口B實現了接口A,接口C實現了接口B,基類D其實只須要接口C的方法,可是此時不得不實現全部的方法

<font color="red">其實形成這個根本緣由:對接口的抽象,設計出現了誤差</font>

畢竟看過JDK源碼或者Spring源碼的同窗,能夠常常發現某一個接口可能實現了一大堆的接口,可是對於普通開發者而言,沒有這種強大的設計能力,就須要在設計的時候多思考,若是發現違背了接口隔離原則的狀況,就應該對接口進行拆分

思惟導圖

Processon分享地址: https://www.processon.com/vie...

PS:須要源文件的小夥伴能夠在文末掃描二維碼,發送【設計模式】便可

設計模式的系列文章推薦

所屬類型 設計模式 標題 & 連接
<font color="red">行爲型模式</font> 策略模式 【一塊兒學系列】之策略模式:好多鴨子啊
<font color="red">行爲型模式</font> 觀察者模式 【一塊兒學系列】之觀察者模式:我沒有在監控你啊
<font color="red">行爲型模式</font> 命令模式 【一塊兒學系列】之命令模式:封裝一個簡單Jedis?
<font color="red">行爲型模式</font> 模板方法模式 【一塊兒學系列】之模板方法:寫SSO我只要5分鐘
<font color="red">行爲型模式</font> 迭代器模式 【一塊兒學系列】之迭代器&組合:雖然有點用不上啦
<font color="red">行爲型模式</font> 狀態模式 【一塊兒學系列】之狀態模式:你聽過「流程」模式嗎?
<font color="red">行爲型模式</font> 職責鏈模式 【一塊兒學系列】之剩下的設計模式們
<font color="red">行爲型模式</font> 備忘錄模式 【一塊兒學系列】之剩下的設計模式們
<font color="blue">結構型模式</font> 裝飾器模式 【一塊兒學系列】之裝飾器模式:不改代碼加強功能?
<font color="blue">結構型模式</font> 適配器模式 & 外觀模式 【一塊兒學系列】之適配器模式:還有外觀模式呢
<font color="blue">結構型模式</font> 組合模式 【一塊兒學系列】之迭代器&組合:雖然有點用不上啦
<font color="blue">結構型模式</font> 代理模式 【一塊兒學系列】之代理模式:是爲了控制訪問啊!
<font color="green">建立型模式</font> 工廠模式
(工廠方法及抽象工廠)
【一塊兒學系列】之工廠模式:產品?產品族?
<font color="green">建立型模式</font> 單例模式 【一塊兒學系列】之單例模式:只推薦三種~
<font color="green">建立型模式</font> 建造者模式 【一塊兒學系列】之剩下的設計模式們

源碼連接

GitHub地址

  • 兼顧了《HeadFirst》以及《GOF》兩本經典書籍中的案例
  • 提供了友好的閱讀指導

LOGO

相關文章
相關標籤/搜索