iOS設計模式彙總

前言

設計模式是有用的抽象化工具,用於解決工程和建築等領域的設計問題。出於一樣的目的,軟件開發領域借用了這一律念,設計模式是一個對象或類的設計模板,用於解決特定領域常常發生的問題。本篇共分8部分涉及22種設計模式:git

  • 對象建立(1~6)
    • 原型模式
    • 簡單工廠模式
    • 工廠模式
    • 抽象工廠模式
    • 建造者(生成器)模式
    • 單例模式
  • 接口適配 (7~9)
    • 適配器模式
    • 橋接模式
    • 外觀模式
  • 對象去耦 (10~11)
    • 中介者模式
    • 觀察者模式
  • 抽象集合 (12~13)
    • 組合模式
    • 迭代器模式
  • 行爲擴展 (14~16)
    • 訪問者模式
    • 裝飾者模式
    • 責任鏈模式
  • 算法封裝 (17~19)
    • 模板方法模式
    • 策略模式
    • 命令模式
  • 性能與對象訪問 (20~21)
    • 享元模式
    • 代理模式
  • 對象狀態 (22)
    • 備忘錄模式

Design Partten

對象建立

1、原型模式

  1. 什麼是原型模式?
    使用原型實例指定建立對象的種類,並經過複製這個對象建立新的對象。

原型模式實際上是經過一個對象爲模板建立另一個可定製的對象,並且不須要知道任何的建立細節。github

  1. 何時使用原型模式?算法

    • 須要建立的對象應該獨立於其類型和建立方式。
    • 須要實例化的類是在運行時決定的。
    • 不想要與產品層次相對應的工廠層次。
    • 不一樣類的實例間的差別僅是狀態的若干組合。所以複製相應數量的原型比手工實例化更加方便。
    • 類不容易建立,好比每一個組件可把其餘組件做爲子節點的組合對象。複製已有的組合對象並對副本進行修改會更加容易。
  2. 深拷貝與淺拷貝設計模式

    • 淺拷貝,指針級拷貝,拷貝出的新實例依舊指向源內存空間,不論修改原來的實例或者拷貝出的實例,都會影響到另外一個(由於指針指向同一塊內存)。
    • 深拷貝,內存級拷貝,會開闢新的內存空間,修改原來的實例或者拷貝的實例,另外一個不受到影響。

    iOS中默認的-copy是淺拷貝,若要深拷貝,須要遵照<NSCopying>協議,重寫-copyWithZone方法。數組

2、簡單工廠模式

  1. 什麼是簡單工廠模式?
    簡單工廠模式(Simple Factory Pattern),又稱爲靜態工廠方法(Static Factory Method)模式,在簡單工廠模式中,能夠根據參數的不一樣返回不一樣類的實例。簡單工廠模式專門定義一個類來負責建立其餘類的實例,被建立的實例一般都具備共同的父類。
  2. 簡單工廠模式的優勢
    • 將對象的建立和對象自己業務處理分離能夠下降系統的耦合度,使得二者修改起來都相對容易。
    • 當你須要什麼,只須要傳入一個正確的參數,就能夠獲取你所須要的對象,而無須知道其建立細節。
    • 在調用工廠類的工廠方法時,因爲工廠方法是靜態方法,使用起來很方便,可經過類名直接調用,並且只須要傳入一個簡單的參數便可,修改參數時無須修改任何源代碼。
  3. 簡單工廠模式的缺點
    • 簡單工廠模式最大的問題在於工廠類的職責相對太重,增長新的產品須要修改工廠類的判斷邏輯,這一點與開閉原則是相違背的。

簡單工廠模式Demo(計算器)安全

3、工廠模式

  1. 什麼是工廠模式?
    定義建立對象的接口,讓子類決定實例化哪個類。工廠方法使得一個類的實例化延遲到了子類。網絡

  2. 何時使用工廠模式?數據結構

    • 編譯時沒法準確預期須要建立對象的類。
    • 類想要其子類決定在運行時建立什麼類型的實例。
    • 類有若干輔助類爲其子類,而你想將返回哪一個子類這種信息局部化。
  3. 工廠模式的優點
    和直接建立具體對象相比,使用工廠方法建立對象算是最佳的作法。
    工廠方法讓客戶端能夠要求由工廠方法建立的對象擁有一組共同的行爲。
    所以,向類層次結構中引入新的具體產品並不須要修改客戶端代碼,由於返回的任何具體對象的接口跟客戶端一直使用的接口相同。架構

  4. Cocoa Touch中的工廠方法
    工廠方法在Cocoa Touch中使用極爲普遍,以NSNumber爲例,它提供了不少的建立方法,好比-numberWithBool-numberWithInt他們傳入不一樣類型的參數,得到NSNumber實例。框架

工廠模式Demo(計算器)

4、抽象工廠

  1. 什麼是抽象工廠?
    提供一個建立一系列相關或者相互依賴對象的接口,而無需指定他們的具體類。

    若是有多個類共有相同的行爲,但實際實現不一樣,則可能須要某種抽象類型作爲他們的父類,抽取其餘們共同的行爲到父類中。

    例如,咱們知道普通的披薩餅是什麼樣子,在點餐的時候能預計到端上來的是什麼。當咱們說"出去吃披薩"時,這裏的「披薩」其實就是一個抽象類型,定義了披薩餅應該共同具備的特徵。可是,從不一樣的店咱們獲得同一披薩餅(好比意大利披薩餅、臘腸披薩餅)的味道大不相同。由於有太多類型的披薩餅,咱們簡單地將其叫作「披薩餅」以稱呼這種特定類型的食品。

    父類的類方法-getFactory僅僅只是返回具體的(合適需求的)工廠類。其子類不該該重載這個方法。-getFactory方法根據配置返回一個具體的工廠實例。

  2. 抽象工廠和工廠模式的比較
    這二者在不少方面都很類似,他們都用於相同的目的:建立對象而不讓客戶端知曉建立細節,他們的對好比下:

抽象工廠 工廠模式
建立方式 對象組合建立抽象產品 類繼承建立抽象產品
建立種類 建立多系列產品 建立一種產品
如何擴展 修改父類的接口才支持新產品 子類建立者重載工廠方法以建立新的產品

抽象工廠Demo(地圖引擎)

5、建造者(生成器)模式

  1. 什麼是建造者模式 將一個複雜對象的構建與他的表現分離,使得一樣的構建過程能夠建立不一樣的表現。

    它能夠將一個產品的內部表象與產品的生成過程分割開來,從而可使一個建造過程生成具備不一樣內部表象的產品對象。
    若是咱們用了建造者模式,那麼用戶只須要指定須要建造的類型就能夠獲得他們的對象實例,而無需關心建造過程和細節。

    在此模式中,除了用戶和其所需的產品,還有兩個重要的角色Director(指導者)Builder(生成器)

    • Director知道Builder應該建造什麼,以參數向其提供缺乏的信息來建立特定產品。
    • Builder是一個抽象接口,聲明瞭一個-build方法,該方法由ConcreBuilder實現,以構造實際的產品,ConcreBuilder有一個-getResult方法,向客戶端返回建造完畢的結果。
  2. 什麼時候使用建造者模式

    • 須要建立涉及各類部件的複雜對象。建立對象的算法應該獨立於部件的裝配方式。常見例子是構建組合對象。
    • 構建過程須要以不一樣的方式(好比,部件或者表現不一樣的組合)構建對象。
  3. 建造者模式和抽象工廠的對比
    抽象工廠和建造者模式在 抽象對象建立方有許多類似之處,可是,兩者卻大不相同。

    • 建造者模式關注的是分步驟建立複雜對象,不少時候,同一類型的對象能夠以不一樣的方式建立。建造者模式在多步建立過程的最後一步返回產品。
    • 抽象工廠的重點在於建立簡單或者複雜產品的套件。抽象工廠當即返回產品。
    建造者模式 抽象工廠
    象的複雜程度 構建複雜對象
    須要的步驟 多步建立
    建立方式種類 多種方式建立
    返回對象的時機 建立過程的最後一步
    建立結果 專一一個特定的產品
  4. 總結
    生成器模式能幫助構建涉及部件與表現的各類組合的對象。沒有這一模式,知道構建對象所需細節的Director可能會最終變成一個極其複雜的類。帶有無數用於構建同一類的各類表現的內嵌算法。而這些算法本應該獨立於該對象的組成部分以及他們的裝配過程。

建造者模式Demo(畫卡通人)

6、單例模式

  1. 何爲單例模式

    單例模式:保證一個類僅有一個實例,而且提供一個訪問它的全局訪問點。

    單例模式幾乎是設計模式中最簡單的了。它的意圖是使得類的一個對象成爲系統中的惟一實例。要實現這一點,能夠從客戶端對其進行實例化開始。所以,須要用一種只容許生成對象類惟一實例的機制來「阻止」全部想要生成對象的訪問。

  2. 什麼時候使用單例模式

    • 類只能有一個實例,並且必須從一個爲人熟知的訪問點對其進行訪問,(好比工廠方法)。
    • 這個惟一的實例只能經過子類化進行擴展,並且擴展的對象不會破壞客戶端代碼。
  3. Objective-C實現單例模式
    在OC中,單例模式的實現目前分爲兩種:

    • 原始實現
      遵照<NSCopying>協議重寫-alloc方法和-copy方法,考慮線程安全。
    • GCD實現
      藉助GCD的dispatch_once實現

單例模式Demo(一個嚴謹的單例)

接口適配

7、適配器

  1. 何爲適配器模式

    適配器模式,用於鏈接兩種不一樣種類的對象,使其毫無問題地協同工做。其思想比較簡單:適配器實現客戶端所須要的某種接口的行爲,同時,它又鏈接到一個具備(徹底)不一樣接口行爲的對象。一邊是客戶端懂得如何使用的目標接口,另外一邊是客戶端一無所知的被適配者,適配器在兩者之間。它的主要做用是把被適配者的行爲傳遞給管道另外一端的客戶端。

    定義:將一個類的接口轉換成客戶但願的另一個接口。Adapter模式使得本來接口不兼容而不能在一塊兒工做的類能夠一塊兒工做了。

  2. 適配器分類

    • 類適配器
      它是經過類繼承實現的,而Objective-C有着協議(Protocol)這一語言特性,因此在Objective-C中,類能夠實現協議,同時又繼承自父類,從而達到C++中多繼承的效果。
      要在OC中實現類適配器,首先須要有定義了客戶端要使用的一套行爲的協議,而後用具體的適配器類來實現這個協議,適配器類同時也繼承被適配者。

    • 對象適配器
      與上面的類適配器不一樣,對象適配器不繼承被適配者,而是組合了一個對他的引用。

  3. 類適配器與對象適配器的比較

    類適配器 對象適配器
    只針對單一具體的Adaptee類,把Adaptee適配到target 能夠適配多個Adaptee及子類
    易於重載Adaptee的行爲,覺得是經過直接的子類化進行的適配 難以重載,須要藉助子類的對象而非Adaptee自己
    只有一個Adaptee對象,無需額外的這鎮間接訪問Adaptee 須要額外的指針間接訪問Adaptee並適配其行爲

    Adaptee:被適配者
    Target:目標接口

  4. 什麼時候使用適配器模式

    • 已有類的接口與需求不匹配
    • 想要一個可複用的類,該類可以同可能帶有不兼容接口的其餘類協做。
    • 須要適配一個類的幾個不一樣子類,但是讓每個子類去子類化一個類適配又不現實,那麼可使用對象適配器(委託)來適配其父類的接口。

8、橋接模式

  1. 何爲橋接模式?
    將抽象部分與它的實現部分分離,使它們均可以獨立地變化。

    所謂抽象與它的實現分離,這並非說,讓抽象類與其派生類分離,由於這沒有任何意義。實現指的是抽象類和它的派生類用來實現本身的對象。

    實現系統時可能有多角度分類,每一種分類都有可能變化,那麼就把這種多角度分離出來,讓他們獨立變化,減小他們之間的耦合。

  2. 合成/聚合複用原則

    • 繼承的弊端
      對象的繼承關係在編譯時就已經定好了,因此沒法在運行時改變從父類繼承的實現。子類的實現與其父類有着很是緊密的依賴關係,以致於父類實現中任何變化必然會致使子類發生變化。當須要複用子類時,若是繼承下來的實現不適合新的問題,則父類必須重寫或者被其餘更適合的類替換。這種依賴關係限制了靈活性並最終限制了複用性。

    • 合成/聚合複用原則
      合成(也叫作組合,Composition)和聚合(Aggregation)都是關聯的特殊種類。聚合表示一種弱的「擁有「關係,體現的是A對象能夠包含B對象,但B對象不是A對象的一部分;合成則是一種強的」擁有「關係,體現了嚴格的部分和總體的關係,部分和總體的生命週期同樣。

      好比:大雁有兩個翅膀,翅膀與大雁是部分和總體的關係,而且他們的生命週期相同,因而大雁和翅膀就是合成關係。大雁是羣居動物,每隻大雁都屬於一個雁羣,一個雁羣能夠有多隻大雁,因此,大雁和雁羣是聚合關係。

    優先使用對象的組合/聚合將有助於保持每一個類被封裝,並集中在單個任務上。這樣類和類繼承層次會保持較小規模,而且不太可能增加爲不可控制的龐然大物。

  3. 什麼時候使用橋接模式

    • 不想在抽象與實現之間造成固定的綁定關係(這樣能夠在運行時按需切換實現)
    • 抽象及其實現都應能夠經過子類化獨立擴展。
    • 對抽象的實現進行修改不該該影響客戶端代碼。
    • 若是每一個實現須要額外的子類以細化抽象,則說明有必要把他們分紅兩個部分。
    • 想在帶有不一樣抽象接口的多個對象之間共享一個實現。

橋接模式Demo(手機軟件系統)

9、外觀模式

  1. 何爲外觀模式
    定義:爲系統中的一組接口提供一個統一的接口,外觀定義一個高層接口,讓子系統更易於使用。

    外觀模式爲子系統中一組不一樣的接口提供一個統一的接口。外觀定義了上層接口,經過下降複雜度和隱藏子系統之間的通訊及依存關係,讓子系統更易於使用。

  2. 什麼時候使用外觀模式

    • 子系統正在逐漸變得複雜。應用模式的過程當中演化出許多類。可使用外觀模式爲這些子系統類提供一個更簡單的接口。
    • 可使用外觀對子系統進行分層。每一個子系統級別有一個外觀做爲入口點。讓他們經過其外觀進行通訊,能夠簡化他們的依賴關係。
  3. 總結
    當程序逐漸變大變複雜的時候,會有愈來愈多小型的類從設計和應用模式中演化出來。若是沒有一種簡化的方式來使用這些類,客戶端代碼會變得愈來愈複雜和難以理解,並且難以維護,外觀模式有助於提供一中更爲簡單的方法來使用子系統中的這些類。處理這些子系統的默認行爲,可能只是定義在外觀中的簡單方法,而沒必要直接使用這些類。

外觀模式Demo(乘客乘車案例)

對象去耦

10、中介者模式

  1. 何爲中介者模式
    定義:用一個對象來封裝一系列對象的交互方式。中介者使各個對象不須要顯示地相互引用,從而使其耦合鬆散,並且能夠獨立地改變它們之間的交互

    面向對象的設計鼓勵把行爲分散到不一樣的對象中,這種分散可能致使對象之間的相互關聯。在最糟糕的狀況下,全部對象都彼此之間瞭解和相互操做。

    雖然把行爲分散到不一樣對象加強了可複用性,但仍是增長的相互關聯有減小了得到的益處。增長的關聯使得獨享很難或者不能在不依賴其餘對象的狀況下工做。應用程序的總體行爲可能難以改動,由於他分佈於許多對象。

    中介者模式用於解決此類問題,它定義了一個集中的場所,對象之間的交互能夠在一箇中介者對象中處理,其餘對象沒必要彼此交互,所以減小了他們之間的依存關係。

  2. 什麼時候使用中介者模式

  • 對象之間的交互雖然定義明確可是很是複雜,致使一組對象彼此相互依賴並且難以理解。
  • 由於對象引用了許多其餘對象而且與其通信,致使對象難以複用。
  • 想要定製一個分佈在多個類中的邏輯或行爲,又不想生成太多子類。
  1. 中介者模式的優缺點
    中介者模式很容易在系統中使用,也很容易誤用。當系統出現了「多對多」交互複雜的對象羣時,不要急於使用中介者模式,而要先反思系統的設計是否合理。

    • 優勢:
      一、中介者的存在,減小了各個具體類的耦合度,使各個具體類和中介者能夠獨立地改變和複用;

      二、因爲把對象如何協做進行了抽象,將中介者做爲一個獨立的概念並將其封裝在一個對象中,這樣關注的對象就從對象各個自己的行爲轉移到了他們之間的交互上來,也就是站在一個更宏觀的角度去看待系統。

    • 缺點:
      因爲中介者控制了集中化,因而把交互複雜性變爲了中介者的複雜性,這就使得中介者會變得比任何一個具體類都複雜。

  2. 總結
    中介者模式的應用十分普遍,組件化應該算是最貼切的中介者模式的應用場景了,各個組件,獨立開發,維護,組件之間使用中間件進行通信。詳見:iOS 一個輕量級的組件化思路

    雖然對於處理系統的行爲分散於不一樣對象而且對象相互依存的狀況,中介者模式很是有用,可是應該注意避免讓中介者類過於龐大而難以維護。若是已經如此了,能夠考慮使用另外的設計模式把它分解。

中介者模式Demo(同事對話)

11、觀察者模式

  1. 何爲觀察者模式
    定義:定義對象間的一種一對多的依賴關係,當一個對象的狀態發生改變時,全部依賴於它的對象都獲得通知而且被自動更新

    觀察者模式也叫作發佈——訂閱模式。Observer從Subject訂閱通知。ConcreteObserver實現抽象Observer並重載其update方法。一旦Subject的實例須要通知Observer任何的變動,Subject會發送update消息來通知存儲在內部列表中全部註冊的Observer。在ConcreteObserver的update方法的實際實現中,Subject的內部狀態可被取得並在之後進行處理。

  2. 什麼時候使用觀察者模式

    • 有兩種抽象類型相互依賴。將它們封裝在各自的對象中,就能夠對它們單獨進行改變和複用。
    • 對一個對象的改變須要同時改變其餘對象,而不知道具體有多少對象有待改變。
    • 一個對象必須通知其餘對象,而它又不須要知道其餘對象是什麼。
  3. Cocoa Touch框架中的觀察者模式

    • 通知
      Cocoa Touch框架中使用NSNotificationCenter和NSNotification對象實現了一對多的發佈——訂閱模式,他們容許主題與觀察者以一種鬆耦合的方式通訊。二者在通訊時對另一方無需多少了解。

    • 鍵—值觀察
      Cocoa提供了另一種稱爲鍵-值觀察的機制,對象之間能夠經過它獲得其餘對象特定的變動通知。這種機制在MVC(Model-View-Controller)模式的場景中尤爲重要,它讓視圖對象能夠經由控制器層觀察模型對象的變動。

      鍵-值觀察
      箇中心對象爲全部觀察者提供變動通知 被觀察的對象直接向觀 察者發送通知
      要從廣義上關注程序事件 綁定於特定對象屬性的值

抽象集合

12、組合模式

  1. 什麼是組合模式
    定義:將對象組合成樹形結構以表示「部分—總體」的層次結構。組合模式使得用戶對單個對象和組合對象的使用具備一致性。

    組合模式讓咱們能夠把相同基類型(base type)的對象組合到樹狀結構中,其中父節點包含同類型的子節點。換句話說,這種樹狀結構造成"部分-總體"的層次結構。

    樹形結構是既包含對象的組合(容器)又包含做爲葉節點(基元)的單個對象對的一種層次結構。每一個組合體包含的節點能夠是葉節點也能夠是其餘組合體。這種關係在這個層次結構中遞歸重複。客戶端對組合結點和葉節點擁有相同的操做,客戶端在使用時能夠忽略他們之間的差異。

  2. 什麼時候使用組合模式

    • 想得到對象抽象的樹形結構(部分-總體層次結構)。
    • 想讓客戶端統一處理組合結構中的全部對象。
  3. 透明方式與安全方式

    • 透明方式
      在葉節點中也有-add-remove方法,然而葉節點上不須要這些行爲;這樣作的目的是爲了讓他們徹底相同的接口,調用方徹底用處理這種邏輯,這就是透明方式。

    • 安全方式
      若是不但願葉節點上存在上面的方法,那麼在最基本結構(Component)中就不聲明-add-remove方法,而是另外在聲明一個結構(Composite)用來管理子類對象的方法,這樣就能避免透明代理出現的問題,但同時,因爲不夠透明,因此樹葉和樹枝擁有不一樣的接口,客戶端的調用須要作相應的判斷,給調用方帶來了不便。

    兩種方式沒有絕對的優劣,看我的的理解和取捨(類比簡單工廠和工廠模式)。

組合模式Demo(公司組織架構案例)

十3、迭代器模式

  1. 何爲迭代器模式
    定義:提供一種方法順序訪問一個聚合對象中的各個元素,而又不須要暴露獨享的內部表示。

    迭代器提供一種順序訪問聚合對象(集合)中元素的方法,而無需暴露結構的底層表示和細節。遍歷集合中元素的職能從集合自己轉移到迭代器對象。迭代器定義了一個用於訪問集合元素並記錄當前元素的接口。不一樣迭代器能夠執行不一樣的遍歷策略。

  2. 什麼時候使用迭代器模式

    • 須要訪問組合對象的內容,而又不暴露內部表示。
    • 須要經過多種方式遍歷組合對象。
    • 須要提供一個統一接口,用來遍歷各類類型的組合對象。
  3. Cocoa Touch中的迭代器模式

    • NSEnumerator 從iOS2.0開始,可使用NSEnumerator來枚舉NSArray、NSDictionary、NSSet對象中的元素。
    • 基於block的枚舉
      在iOS4中引入了基於塊的枚舉(Block-Based Enumeratoration)
    • 快速枚舉(for-in)
    • 內部枚舉
      NSArry有個實例方法-makeObjectsPerformSelector:,它容許客戶端向數組中每一個元素髮送一個消息,讓其每一個元素執行指定的方法。

迭代器模式Demo(乘客買票案例)

行爲擴展

十4、訪問者模式

  1. 何爲訪問者模式
    定義:表示一個做用於某對象結構中的各元素的操做。它使你能夠在不改變各元素類的前提下定義做用於這些元素的新操做。

  2. 什麼時候使用訪問者模式

    • 一個複雜的對象結構包含不少其餘對象,他們有不一樣的接口,這個對象的實施依賴於其具體類型的操做。
    • 須要對一個組合結構體中的對象進行不少不相關的操做,可是不想讓這些操做「污染」這些對象的類,能夠將相關的操做集中起來,定義在一個訪問者類中,並在須要在訪問者中定義的操做時使用它。
    • 定義複雜結構的類不多修改,單常常須要向其添加新的操做。
  3. 總結
    訪問者模式是擴展組合結構功能的一種強有力的方式。若是組合結構具備精心設計的基本操做,並且結構相對穩定就可使用訪問者模式。

訪問者模式Demo(男人女人案例)

十5、裝飾者模式

  1. 何爲裝飾着模式
    裝飾者模式:動態地給一個對象添加一些額外的職責。就擴展功能來講,裝飾者模式相比生成子類更加靈活。

    Component是定義一個對象接口,能夠給這些對象動態地添加職責。ConcreteComponent是定義了一個具體的對象,也能夠給這個對象添加一些職責。Decorator,裝飾者抽象類,繼承了Component,從外類來擴展Component類的功能,但對於COmponent來講,是無需知道Decorator的存在的。至於ConcreteDecorator就是具體的裝飾對象,起到給Component添加職責的功能。

    在平常開發過程當中,應該減小類繼承的使用,過多地使用類的繼承會致使類數目過於龐大而變得難以維護,而使用組合可讓咱們的系統更具彈性,更加容易修改和擴展。

  2. 什麼時候使用裝飾者模式

  • 想要在不影響其餘對象的狀況下,以動態,透明的方式給單個對象添加職責。
  • 想要擴展一個類的行爲,卻作不到。類定義可能被隱藏,沒法進行子類化;或者,對類的每一個行爲的擴展,爲支持各類功能組合,將產生大量的子類。
  • 對類的職責的擴展是可選的。
  1. 改變對象的「外表」和「內容」

    "外表"變動(裝飾者) 「內容」變動(策略)
    從外部變動 從內部變動
    每一個節點不知道變動 每一個節點知道一組預約義的變動方式

裝飾者模式Demo(給圖片加濾鏡)

十6、責任鏈模式

  1. 何爲責任鏈模式

    定義:使多個對象都有機會處理請求,從而避免請求的發送者和接受者之間發生耦合。此模式將這些對象連城一天鏈,而且沿這條鏈傳遞請求,直到一個對象處理它爲止。

    使用責任鏈模式能夠隨意地增長或修改處理一個請求的結構,加強了對對象指派職責的靈活性。可是可能一個請求到了責任鏈的末端都得不處處理,或者由於沒有正確地配置而得不處處理,須要考慮全面。

  2. 什麼時候使用責任鏈模式

    • 有多個對象能夠處理請求,而處理程序只有在運行時才能肯定。
    • 向一組對象發出請求,而不想顯示指定處理請求的特定處理程序。
  3. 總結

    責任鏈模式能很好地解決大量分支判斷,有效下降了客戶端調用的邏輯複雜度。以上的3個設計模式,都是在擴展對象行爲的同時,對對象進行最少修改甚至不修改。對愈來愈複雜的系統擴展具備極大的借鑑意義。

責任鏈模式Demo(加薪案例)

算法封裝

十7、模板方法模式

  1. 何爲模板方法模式

    定義:定義一個操做中的算法骨架,而將一些步驟延遲到子類中。模板方法使子類能夠從新定義算法的某些y特定步驟而不改變改算法的結構。

    其基本思想是在抽象類的一個方法中定義「標準」算法。這個方法的實現由子類重載實現。這個方法被稱爲「模板」,由於方法定義的算法缺乏一些特定的操做。子類重載基本操做以提供獨特操做供模板方法使用。

  2. 什麼時候使用模板方法模式

    • 須要一次性實現算法的不變部分,並將可變的行爲留給子類實現。
    • 子類的共同行爲應該被提取出來,放到公共類中, 以免代碼重複。現有代碼的差異應該被分離爲新的操做。而後用一個調用這些新操做的模板方法來替換這些不一樣的代碼。
    • 須要控制子類的擴展,能夠定義一個在特定點調用「鉤子(hook)」操做的模板方法。子類能夠經過對鉤子的操做實如今這些點擴展功能。
  3. 模板方法 vs 適配器

模板方法 適配器(委託)模式
父類定義一個通常算法,但缺乏某些特定/可選的信息或者算法,它經過這些缺乏的信息或算法起到一個算法的「食譜」做用 適配器與預先定好的委託接口一塊兒定義一個特定的算法
缺乏的信息有子類經過繼承實現 特定算法由任何對象經過組合來提供

模板方法模式Demo(製做多種三明治)

十8、策略模式

  1. 何爲策略模式
    策略模式定義了算法家族,分別封裝起來,讓他們之間能夠相互替換,此模式讓算法的變化不會影響到使用算法的客戶端

    策略模式中的一個關鍵角色是策略類,它爲全部支持的相關算法聲明瞭一個共同接口。另外,還有使用策略接口來實現先關算法的具體策略類。場景(Context)類的對象配置有一個具體策略對象的實例,場景對象使用策略接口調用由具體策略類定義的算法。

  2. 什麼時候使用策略模式

    • 一個類在其操做中使用多個條件語句來定義許多行爲。咱們能夠把相關的條件分支移到他們本身的策略類中。
    • 須要算法的各類變體。
    • 須要把複雜的、與算法相關的數據結構暴露給客戶端。
  3. MVC中的策略模式
    模型-視圖-視圖控制器(MVC)模式中,控制器決定視圖對模型數據的顯示內容和時機。視圖自己知道如何繪圖,但須要控制器告訴他要顯示的內容。一個視圖若是與不一樣的控制器合做,數據的輸出格式可能同樣,但數據的類型和格式可能隨不一樣控制器的不一樣輸出而不一樣。所以,這種狀況下的控制器是視圖的策略。控制器與視圖之間是一種基於策略模式的關係。

  4. 總結
    策略模式和裝飾者模式有些相似。裝飾器從外部擴展對象的行爲,而各類策略則被封裝在對象之中。因此說裝飾器改變對象的「外表」而策略改變對象的「內容」。

策略模式Demo(商場打折案例)

十9、命令模式

  1. 何爲命令模式

    命令對象封裝瞭如何對目標執行指令的信息,所以,客戶端或調用者沒必要了解目標的任何細節,卻仍能夠對它執行任何已知的操做。經過吧請求封裝成對象,客戶端能夠把它參數化並置入隊列或者日誌中,也能支持撤銷的操做。命令對象將一個或多個動做綁定到特定的接收器。命令模式消除了做爲對象的動做和執行它的接收器之間的綁定。

    定義:將請求封裝爲一個對象,從而可用不一樣的請求對客戶端進行參數化,隊請求排隊或記錄請求日誌,以支持可撤銷操做。命令模式把請求一個操做的對象與知道怎麼執行一個操做的對象分割開

  2. 什麼時候使用命令模式

    • 想讓應用程序支持撤銷和恢復。
    • 想用對象參數化一個動做以執行操做,並用不一樣的命令對象來代替回調函數。
    • 想要在不一樣時刻對請求進行指定、排列和執行。
    • 想記錄修改日誌,這樣在系統故障時,這些修改刻在後來重作一遍。
    • 想讓系統支持事務,事務封裝了對數據的一些列修改。事務能夠建模爲命令對象。
  3. 命令模式的優勢

    1. 比較容易地設計一個命令隊列(waiter的commandList數組)
    2. 在須要的狀況下,能夠很容易地將命令記錄日誌(在Waiter的setOrder記錄)
    3. 容許接收方命令的一方決定是否否決該命令(Cooker類能夠通知Waiter無貨源)
    4. 能夠對請求進行撤銷、修改和重作(能夠修改命令的數量)
    5. 因爲新加的具體命令類不影響其餘類,所以增長新的具體命令類很容易

命令模式Demo(燒烤店的訂單操做)

性能與對象訪問

二10、享元模式

  1. 何爲享元模式

    定義:運用共享技術有效地支持大量細粒度的對象

    實現享元模式須要兩個關鍵的組件,一般是可共享的享元對象和保存他們的池。某種中央對象維護這個池,並從它返回適當的對象實例。工廠是這一角色的理想候選,它經過一個工廠方法返回各類類型的具體享元對象。

    享元模式能夠避免大量很是類似類的開銷。在程序設計中,有時須要生成大量細粒度的類實例來表示數據。若是能發現這些實例除了幾個參數外基本相同,有時可以大幅度地減小須要實例化類的數量。若是能把那些參數移到類實例的外面,在方法調用時將他們傳遞進來,就能夠經過共享大幅度地減小實例的數目。

  2. 什麼時候使用享元模式

    • 應用程序使用不少對象
    • 在內存中保存對象會影響性能
    • 對象的多數特有狀態能夠放到外部而輕量化
    • 移除了外在狀態後,能夠用較少的共享對象替換原來的那組對象
    • 應用程序不依賴對象標識,由於共享對象不能提供惟一標識

二11、代理模式

  1. 何爲代理模式

    定義:爲其餘對象提供一種代理以控制對這個對象的訪問。

    代理模式的思想是使用一個基本跟實體對象行爲相同的代理,客戶端能夠」透明地「使用代理,即沒必要知道所面對的只是一個代理而不是實體對象。在iOS中,使用代理來解耦合。

    使用代理把View層的事件傳遞到Controller中

    把tableView的delegate和dataSource實現到一個單獨的Model或者ViewModel中

  2. 代理的分類

    • 遠程代理(remote proxy)
      爲位於不一樣地址空間或者網絡上的對象提供本地表明
    • 虛擬代理(virtual proxy)
      須要根據須要建立重型對象
    • 保護代理(protection proxy)
      根據訪問權限控制對原對象的訪問
    • 智能引用代理(samrt-reference proxy)
      經過對真正對象的引用進行技術來管理內存,也用於鎖定真正對象,讓其餘對象不能對其進行修改。

8、對象狀態

二12、備忘錄模式

  1. 何爲備忘錄模式

    定義:在不破壞封裝性的前提下,捕捉一個對象的內部狀態,並在改對象以外保存這個狀態。這樣之後就能夠將該對象恢復到原先保存的狀態。

    備忘錄模式有是三個角色:原發器(originator)、備忘錄(memento)、 管理者(caretaker)

    • 原發器(originator)
      負責建立一個備忘錄Memento,用來記錄當前時刻的內部狀態,並可以使用備忘錄恢復內部狀態。originator可根據須要決定Memento存儲originator的內部狀態
    • 備忘錄(memento) 負責存儲originator對象的內部狀態,並防止originator之外的對象訪問備忘錄。
    • 管理者(caretaker)
      負責保存好備忘錄Memento,不能對備忘錄的內容進行檢查或者修改。
  2. 合適使用備忘錄模式

    • 須要保存一個對象(或某部分)在某一時刻的狀態,提供之後恢復到這個時刻的狀態。
    • 用於獲取狀態的接口會暴露實現的細節,須要對外隱藏實現細節。

備忘錄模式Demo(遊戲進度保存於恢復)

相關文章
相關標籤/搜索