常見設計模式要點總結

前言

最近在看《head first 設計模式》,發現每一個章節後的要點總結都是言簡意駭,因此特寫此篇博客對常見的設計模式要點作個總結。
<!-- more -->前端

觀察者模式

在對象之間定義一對多的依賴,這樣一來,當一個對象改變狀態,依賴它的對象都會收到通知,並自動更新java


  • 觀察者模式定義了對象之間一對多的關係
  • 主題(可觀察者)用一個共同對接口來更新觀察者
  • 被觀察者不知道觀察者的細節,只知道觀察者實現了觀察者接口
  • 多個觀察者時,不能夠依賴特定的通知順序

 ●  抽象主題(Subject)角色:抽象主題角色把全部對觀察者對象的引用保存在一個彙集(好比ArrayList對象)裏,每一個主題均可以有任何數量的觀察者。抽象主題提供一個接口,能夠增長和刪除觀察者對象,抽象主題角色又叫作抽象被觀察者(Observable)角色。設計模式

  ●  具體主題(ConcreteSubject)角色:將有關狀態存入具體觀察者對象;在具體主題的內部狀態改變時,給全部登記過的觀察者發出通知。具體主題角色又叫作具體被觀察者(Concrete Observable)角色。多線程

  ●  抽象觀察者(Observer)角色:爲全部的具體觀察者定義一個接口,在獲得主題的通知時更新本身,這個接口叫作更新接口。併發

  ●  具體觀察者(ConcreteObserver)角色:存儲與主題的狀態自恰的狀態。具體觀察者角色實現抽象觀察者角色所要求的更新接口,以便使自己的狀態與主題的狀態 像協調。若是須要,具體觀察者角色能夠保持一個指向具體主題對象的引用。學習

裝飾者模式

動態的將責任加到對象上,想要擴展功能,裝飾者提供有別於繼承的另外一種選擇spa


  • 裝飾者模式意味着一羣裝飾者類,這些類用來包裝具體組件
  • 裝飾者類都通過接口或繼承實現
  • 能夠用無數個裝飾者包裝一個組件
  • 裝飾者會致使設計中出現許多小對象,過分使用會讓程序複雜

在裝飾模式中的角色有:線程

  ●  抽象構件(Component)角色:給出一個抽象接口,以規範準備接收附加責任的對象。設計

  ●  具體構件(ConcreteComponent)角色:定義一個將要接收附加責任的類。代理

  ●  裝飾(Decorator)角色:持有一個構件(Component)對象的實例,並定義一個與抽象構件接口一致的接口。

  ●  具體裝飾(ConcreteDecorator)角色:負責給構件對象「貼上」附加的責任。

工廠模式

簡單工廠:定義了一個建立對象的接口,但由子類決定要實例化的類是哪個。

抽象工廠:提供一個接口,用於建立相關或依賴對象的家族而不須要明確指定具體的類


  • 全部的工廠都是用來封裝對象的建立
  • 工廠方法使用繼承:把對象的建立委託給子類,子類實現工廠方法來建立對象
  • 抽象工廠使用對象組合:對象的建立被實如今工廠接口所暴露出來的方法中
  • 抽象工廠建立相關的對象家族,不須要依賴他們的具體類
  • 依賴倒置原則,依賴於抽象而非具體類型

下圖是簡單工廠模式的uml圖

簡單工廠的關注點是產品,如上圖中的CpuFactory,MainboardFactory。當咱們須要新增一個產品的時候(例如memory 就不須要對原有代碼進行修改),可是當咱們須要新增一種cpu的時候(例如huawei cpu)簡單工廠就須要對原有代碼改動了,因而咱們引入第二種抽象工廠。

抽象工廠的關注點是產品族,如上圖中的IntelFactory,AmdFactory。當咱們須要新增一個產品族的時候(例如HuaweiFactory 就不須要對原有代碼進行修改),可是當咱們須要新增一種產品的時候(例如memory)抽象工廠就須要對原有代碼改動了。

以上兩種工廠模式,各有優劣。

單例模式

確保一個類只有一個實例並提供全局訪問點


  • 單例模式確保程序中一個類最多隻有一個實現
  • 單例模式提供訪問者合格實例對全局訪問點
  • Java中實現單例模式須要私有構造器, 一個靜態方法和一個靜態變量
  • 必須假設全部的程序都是多線程的,考慮併發的問題
  • 若是使用多個類加載器,可能致使單例模式失效產生多個實例

推薦一種單例模式的最佳實踐

public class SingleTon {
    private SingleTon(){}
    
    private static class InstanceHolder{
        private final static SingleTon singleTon = new SingleTon();
    }
    
    public SingleTon getSingleTon(){
        return InstanceHolder.singleTon;
    }
}

適配器模式/門面模式

適配器模式:將一個類的接口轉換成指望的另外一個接口,適配器讓本來不兼容的類能夠合做無間

門面模式:提供了一個統一的接口用來訪問子系統的一羣接口。外觀定義了一個高層接口使得子系統更加易用


  • 當須要使用一個現有的類而其接口並不符合你的須要時,使用適配器
  • 適配器將一個對象包裝起來以改變其接口,裝飾者將一個對象包裝起來以增長新的行爲和責任,門面模式將一羣對象「包裝」簡化其接口
  • 當須要簡化並贊成一個很大的接口或者一羣複雜的接口時使用門面模式
  • 門面模式能夠從一個複雜的子系統中解耦
  • 使用一個門面模式須要將子系統組合進外觀中,而後將工做委託給子系統執行

適配器uml圖

模式所涉及的角色有:

  ●  目標(Target)角色:這就是所期待獲得的接口。注意:因爲這裏討論的是類適配器模式,所以目標不能夠是類。

  ●  源(Adapee)角色:如今須要適配的接口。

  ●  適配器(Adaper)角色:適配器類是本模式的核心。適配器把源接口轉換成目標接口。顯然,這一角色不能夠是接口,而必須是具體類

門面模式相對比較簡單

上圖是我暑假在阿里實習作的一個小需求。其中核身組件就用到了門面模式,將核身組件這個領域對象暴露給前端,使得前端沒必要關注具體的每一個核身項,從一個複雜的子系統中解耦。

代理模式

一個替身或佔位符以訪問這個對象


  • 代理模式爲另外一個對象提供表明,以便控制客戶對對象的訪問
  • 代理在結構上相似裝飾者但目的不一樣
  • 裝飾者模式爲對象加上行爲,而代理則是控制訪問

在代理模式中的角色:

  ●  抽象對象角色:聲明瞭目標對象和代理對象的共同接口,這樣一來在任何可使用目標對象的地方均可以使用代理對象。

  ●  目標對象角色:定義了代理對象所表明的目標對象。

  ●  代理對象角色:代理對象內部含有目標對象的引用,從而能夠在任什麼時候候操做目標對象;代理對象提供一個與目標對象相同的接口,以即可以在任什麼時候候替代目標對象。代理對象一般在客戶端調用傳遞給目標對象以前或以後,執行某個操做,而不是單純地將調用傳遞給目標對象。

總結

想要學習設計模式的初衷是,如何寫出更靈活,更健壯,更符合規範的代碼。也確實從設計模式的學習中感覺到了面向對象的強大,不過紙上得來終覺淺,絕知此事要躬行。

參考文檔:

《Head First 設計模式》

相關文章
相關標籤/搜索