設計模式知識梳理(1) 設計模式概述

澤毛發表於2017-12-21

一、概述

去年時候看過<<Head First 設計模式>>這本書,也記了一些用例和筆記,下面是當時各模式對應的筆記,現在看起來也都忘的差不多了,就把以前的筆記當作是一個目錄,打算花半個到一個月的時間,好好地總結一下每個設計模式。

二、各設計模式詳解

2.1 策略模式

定義了算族,分別封裝起來,讓它們之間可以互相替換,此模式讓演算法的變化獨立於使用演算法的客戶。

2.2 觀察者模式

2.3 裝飾者模式

  • 裝飾者物件和被裝飾者物件具有同樣的超型別。
  • 你可以用一個或多個裝飾者包裝一個物件。
  • 既然裝飾者和被裝飾物件具有同樣的超型別,所以在任何需要原始物件(被包裝的場合),可以用裝飾過的物件代替它。
  • 裝飾者可以在所委託被裝飾者的行為之前與/或之後,加上自己的行為,以達到特定的目的。
  • 物件可以在任何時候被裝飾,所以可以在執行時動態地、不限量地用你喜歡的裝飾者來裝飾物件。

2.4 簡單工廠

簡單工廠其實並不是一個設計模式,反而比較像是一種程式設計習慣。

2.5 工廠方法模式

定義了一個建立物件的介面,但由子類決定要例項化的類是哪一個,工廠方法讓類把例項化推遲到子類。

2.6 抽象工廠模式

提供一個介面,用於建立相關或依賴物件的家族,而不需要明確指定具體類。

2.7 單件模式

確保一個類只有一個例項。

2.8 介面卡模式

  • 客戶和被適配者是解耦的。
  • 包裝某些物件,讓它們的介面看起來不像自己而像是別的東西,因為這樣就可以在設計中,將類的介面轉換成想要的介面,以便實現不同的介面。
  • 將一個介面轉換成另一個介面,以符合客戶的期望。
  • 客戶使用介面卡的過程:客戶通過目標介面呼叫介面卡的方法對介面卡發出請求,介面卡使用被適配者介面把請求轉換成被適配者的一個或多個呼叫介面,客戶接收到呼叫的結果,但並未發覺這是介面卡在起作用。
  • 介面卡模式將一個類的介面,轉換成客戶期望的另一個介面,介面卡讓原本介面不相容的類可以合作無間。
  • 如果在一段時間之後,我們想要改變介面,介面卡可以將改變的部分封裝起來,客戶就不必為了應對不同的介面而每次跟著修改。
  • 這個介面卡模式充滿著良好的OO設計原則:使用物件組合,以修改的介面包裝被適配者,這種做法還有額外的優點,那就是,被適配者的任何子類,都可以搭配著介面卡使用。

2.9 外觀模式

將一個或數個類的複雜的一切都隱藏在背後,只顯出一個乾淨美好的外表。 提供了一個統一的介面,用來訪問子系統中的一群介面,外觀定義了一個高層介面,讓子系統更容易使用。 不要贏得太多的朋友和影響太多的物件: 就任何物件而言,在該物件的方法內,我們只應該呼叫屬於以下範圍的方法:

  • 該物件本身。
  • 被當做方法的引數而傳進來的物件。
  • 此方法建立或例項化的任何物件。
  • 物件的任何元件。
  • 如果某物件是呼叫其它的方法的返回結果,不要呼叫該物件的方法。

介面卡將一個物件包裝起來以改變其介面; 裝飾者將一個物件包裝起來以增加新的行為和責任; 外觀將一群物件“包裝”起來以簡化其介面;

2.10 模板方法模式

在一個方法中定義一個演算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類可以在不改變演算法結構的情況下,重新定義演算法中的某個步驟。

Comparator<T>正是使用這種模式達到排序的效果。

好萊塢準則:我們允許低層元件將自己掛鉤到系統上,但是高層元件會決定什麼時候和怎樣使用這些低層元件,高層元件對待低層元件的方式是"別呼叫我們,我們會呼叫你"

策略模式和模板方法模式都封裝演算法,一個用組合,一個用繼承。 工廠方法是模板方法的一種特殊版本。

2.11 迭代器模式

提供一種方法順序訪問一個聚合物件中的各個元素,而又不暴露其內部的表示。

  • 如果你有一個統一的方法來訪問聚合中的每一個物件,你就可以編寫多型的程式碼和這些聚合搭配,使用。
  • 迭代器模式把在元素之間遊走的責任交給迭代器(createIterator),而不是聚合物件(xxMenu),這不僅讓聚合的介面和實現變得更簡潔,也可以讓聚合更專注在它所專注的事情上面,而不必去理會遍歷的事情。

2.12 組合模式

允許你將兌現組合成樹形結構來表現"整體/部分"層次結構,組合能讓客戶以一致的方式(MenuComponent)處理個別物件以及物件組合。

  • 組合模式讓我們能用樹形方式建立物件的結構,樹裡面包含了組合以及個別物件。
  • 使用組合結構,我們能把相同的操作應用在組合和個別物件上,換句話說,在大多數情況下,我們可以忽略物件組合和個別物件之間的差別。
  • 組合以單一責任設計原則換取透明性,通過讓元件的介面同時包含一些管理子節點和葉節點的操作,客戶就可以將組合和葉節點一視同仁,也就是說,一個元素究竟是組合還是葉節點,對客戶是透明的。

我們應該努力讓一個類只分配一個責任。

2.13 狀態模式

(狀態 -> 類,行為 -> 方法)

將每個狀態的行為都放在各自的類中,那麼每個狀態只要實現它自己的動作就可以了,糖果機只需要委託給代表當前狀態的狀態物件。

  • 首先,定義一個State介面,在這個介面內,糖果機的每個動作都有一個對應的方法。
  • 然後為機器中的每個狀態實現狀態類,這些類將負責在對應的狀態下進行機器的行為。
  • 最後,我們要擺脫舊的條件程式碼,取而代之的是,將動作委託到狀態類。

Context也可以決定狀態轉換的流向,狀態轉換是固定的時候,就適合放在Context中,然後,當轉換是更動態的時候,通常就會放在狀態類中。 將狀態轉換放在狀態類的缺點是,狀態類之間產生了依賴。

狀態模式允許物件在內部狀態改變時改變它的行為,物件看起來好像修改了它的類。(通過在Context內簡單地改變狀態物件來改變context的行為)

2.14 代理模式

為另一個物件提供一個替身或佔位符以控制對這個物件的訪問。

  • 在某些情況下,一個客戶不想或者不能直接引用另一個物件,而代理物件可以在客戶端和目標物件之間起到中介的作用。
  • 抽象角色:宣告真實物件和代理物件的共同介面。
  • 代理角色:代理物件角色內部含有對真實物件的引用,從而可以操作真實物件,同時代理物件提供與真實物件相同的介面以便在任何時刻能夠代替真實物件。
  • 真實角色:代理角色所代表的真實物件,是我們最終要引用的物件。

2.15 橋接模式

通過將實現和抽象放在兩個不同的類層次中而使它們可以獨立地改變。 優點:

  • 將實現予以解耦,讓它和介面之間不再永久繫結。
  • 抽象和實現可以獨立擴充套件,不會影響到對方。
  • 對於"具體的抽象類"所做的改變,不會影響到客戶。 用途和缺點:
  • 適合使用在需要跨越多個平臺的圖形和視窗系統上。
  • 當需要用不同的方式改變介面和實現時,你會發現橋接模式很好用。
  • 增加了複雜度。

2.16 生成器模式

使用生成器模式封裝一個產品的構造過程,並允許按步驟構造。

2.17 責任鏈模式

當你想要讓一個以上的物件有機會能夠處理某個請求的時候,就使用責任鏈模式。

2.18 享元模式

通過使用共享的方式,達到高效地支援大量的細粒度物件。

2.19 直譯器模式

直譯器模式是類的行為模式,給定一個語言以後,直譯器模式可以定義出其文法的一種表示,並同時提供一個直譯器,客戶端可以通過這個直譯器來解釋這個語言中的句子。 模式涉及的角色:

  • 抽象表示式:宣告一個所有的具體表示式角色都需要實現的抽象介面。這個介面主要是一個interpret()方法,稱做解釋操作。
  • 終結符表示式:實現了抽象表示式角色所要求的介面,主要是一個interpret()方法;文法中的每一個終結符都有一個具體終結表示式與之相對應。比如有一個簡單的公式R=R1+R2,在裡面R1R2就是終結符,對應的解析R1R2的直譯器就是終結符表示式。
  • 非終結符表示式:文法中的每一條規則都需要一個具體的非終結符表示式,非終結符表示式一般是文法中的運算子或者其他關鍵字,比如公式R=R1+R2中,“+"就是非終結符,解析“+”的直譯器就是一個非終結符表示式。 (4)環境角色:這個角色的任務一般是用來存放文法中各個終結符所對應的具體值,比如R=R1+R2,我們給R1賦值100,給R2賦值200。這些資訊需要存放到環境角色中,很多情況下我們使用Map來充當環境角色就足夠了。

2.20 中介者模式

用一箇中介者物件封裝一系列的物件互動,中介者使各物件之間不需要顯示地相互作用,從而使偶爾鬆散,而且可以獨立地改變它們之間的互動。

  • 中介者介面類:定義好同事類物件到中介者物件的介面,用於各同事類的通訊,一般包括一個或幾個抽象物件的方法,由子類去實現。
  • 中介者實現類:從一個同事類中接收訊息,同時影響其它同事。
  • 同事類:如果一個物件會影響其它物件,同時也會被其它物件影響,那麼稱它為同事類。在中介者模式中,同事類必須通過中介者通訊。

2.21 備忘錄模式

備忘錄物件是一個用來儲存另一個物件內部狀態的快照的物件,在不破壞封裝的前提下,把物件的狀態儲存起來,等待之後恢復。

  • 備忘錄角色 將發起人的內部狀態儲存起來; 備忘錄可以保護其內容不被髮起人物件之外的任何物件看到;
  • 發起人角色 建立一個含有當前內部狀態的備忘錄物件; 使用備忘錄物件儲存其狀態;
  • 負責人角色 負責儲存備忘錄物件; 不檢查備忘錄物件的內容;

2.22 原型模式

用原型例項指定建立物件的種類,並且通過拷貝這些原型建立新的物件。 適用性:

  • 當一個系統獨立於它的產品建立、構成和表示時。
  • 當要例項化的類是在執行時指定。
  • 為了避免建立一個與產品類層次平行的工廠類層次時。 原型模式優點:
  • 使用原型模式建立物件比直接new一個物件要好,因為Objectclone方法是一個native方法,它直接操作記憶體中的二進位制流。
  • 簡化物件的建立。 原型模式的注意事項:
  • 不會呼叫物件的構造方法。
  • 只會拷貝物件中的基本資料型別,對於陣列、容器物件、引用物件等都不會拷貝,也就是淺拷貝,如果需要複製這些物件中的內容,那麼要進行深拷貝。

2.23 訪問者模式

訪問者模式的目的是封裝一些施加於某種資料元素結構之上的操作,當這些操作需要更改的話,接受這個操作的資料結構可以不變,即把資料結構和作用其上的操作分開。

  • 抽象訪問者角色:宣告一個或多個方法的介面,所有的具體訪問者必須實現這些方法。
  • 具體訪問者角色:實現抽象訪問者所宣告的介面。
  • 抽象節點角色:宣告一個接受操作,接受一個訪問者作為引數。
  • 具體節點角色:實現了抽象節點所規定的接受操作。
  • 結構物件角色:可以遍歷結構中所有元素,如果需要,提供一個高層次的介面讓訪問者物件可以訪問每一個元素。

相關文章