原則
咱們全部人都看過科幻電影,都看到過將來場景中人類和機器人和平相處的場景java
爲了讓擁有自主智能
的機器人不失控,人類爲機器人制定了三大定律:git
固然有時也會出現下面的狀況,機器人和人類開始互爲陣營,各自爲敵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> | 建造者模式 | 【一塊兒學系列】之剩下的設計模式們 |