iOS開發小記-設計模式(持續更新)

MVC、MVP、MVVM


關於三者的比較說明,能夠看Casa醬的這篇iOS應用架構談 view層的組織和調用方案,巧神的被誤解的 MVC 和被神化的 MVVM篇幅有限,也能夠瞅一眼~html

原型模式


原型模式:使用原型實例指定建立對象的種類,並經過複製這個原型建立新的對象。ios

它是一個很是簡單的設計模式,基於「複製」操做。複製指用同一模具生產一系列的產品。模具所基於的物品稱爲原型。 此模式的最低限度是生成對象的真實副本,以用做同一環境下其餘相關事物的基礎。設計模式

  • 什麼時候使用

通俗來講,若是要建立的新對象和自身差別並不大,其行爲略有不一樣,且複製自身比手工實例化要好,就可使用原型模式。bash

例如我有一個Person實例A,我須要一個跟A僅Name不一樣,可是其他屬性均相同的新對象B,若是使用者經過新建實例並將A的全部屬性賦值給B,這無疑是至關麻煩的,這時咱們就可使用B = [A clone]來複制A的屬性,從而節省大量精力,提升了複用性也便於維護。markdown

  • Cocoa中的應用

最多見的應用就是深複製,如NSMutableArray = [NSArray mutableCopy]網絡

注:淺複製不屬於原型模式,它不知足上面說到的原型模式的最低限度,僅僅是指針拷貝。
複製代碼
  • 實際開發中的應用

比較常見的狀況就是對自定義對象進行拷貝的時候,咱們須要經過對自定義對象實現NSCopying協議及其方法- (id)copyWithZone:(NSZone *)zone多線程

單例模式


單例模式:保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。它幾乎是全部設計模式中最簡單的一個了。架構

  • 什麼時候使用
  1. 類只能有一個實例,並且必須從一個爲人熟知的訪問點對其進行訪問。
  2. 這個惟一的實例只能經過子類化進行擴展,並且擴展的代碼不會破壞客戶端的代碼。 通常來說,工程中若是須要頻繁使用某一個類,並且能夠只須要一個該類的實例,而且經過它共享資源,那麼咱們就能夠考慮使用單例模式。
  • Cocoa中的應用

最多見的就是[UIApplication sharedApplication]mvc

  • 實際開發中的應用

例如一些管理類xxManager,設置類xxConfiger等等,都是會頻繁使用而且須要共享資源保存臨時狀態,就可使用單例。 關於多線程下加鎖保證只建立一個實例,咱們可使用@synchronized、NSLock等,更推薦使用dispatch_once,性能更優。 甚至咱們還可使用宏來實現單例。框架

  • Objective-C下的問題

因爲Objective-C並不能像C++,Java中同樣可以隱藏構造函數,小夥伴們仍是能夠alloc/init來建立對象,通常有兩種解決方案:

  1. 從OC的對象建立角度出發,就是把建立對象的各類入口給封死了。alloc,copy等等,不管是採用哪一種方式建立,我都保證給出的對象是同一個。
  2. 溫柔派就直接告訴外面,alloc,new,copy,mutableCopy方法不能夠直接調用。不然編譯不過。

工廠方法模式


工廠方法模式:也叫作虛構造器。定義建立對象的接口,讓子類決定實例化哪個類。工廠方法使得一個類的實例化延遲到其子類。

通俗來說,對於有多種相似的產品,咱們能夠將產品的公有屬性和方法抽象爲一個產品基類,將生產產品的工廠抽象爲一個工廠基類,並暴露返回產品對象的工廠方法,各自產品的工廠繼承自工廠基類,並重載該工廠方法以返回對應的產品對象。

  • 什麼時候使用
  1. 編譯時沒法準確預期要建立的對象的類。
  2. 類想讓子類決定運行時建立什麼。
  3. 類有若干個輔助類爲其子類,而你想將返回哪一個子類這一信息局部化。
  • 實際開發中的應用

例如一開始的股票詳情界面,有指數、滬深、港股、美股等等,分別有一個基於TKHqBaseStockDetailViewController的詳情子類,以及基於TKHqBaseStockDetailFactory的工廠子類,工廠提供了一個建立詳情的方法,使用者可使用對應的工廠子類來獲取想要的詳情子類。

注:咱們也能夠經過傳遞股票信息在工廠內部經過枚舉來直接建立對應的詳情子類,而不經過工廠子類來建立,這種就是簡單工廠。
複製代碼

抽象工廠模式


抽象工廠模式:提供一個建立一系列相關或相互依賴對象的接口,而無需指定它們具體的類。

通俗來說,咱們能夠提供一個工廠基類,其中包含了建立一系列產品的工廠方法,而且經過使用預處理或者枚舉來生成不一樣的工廠子類,這些工廠子類中都實現了基類的工廠方法,並根據本身的需求在創造產品的工廠方法中獲取想要的具體的產品子類。

  • 與工廠方法的區別
  1. 抽象工廠使用對象組合來建立抽象產品,工廠方法是經過繼承來建立抽象產品。
  2. 抽象工廠用於建立多系列產品,工廠方法用於建立一個產品。
  3. 若是要支持新的產品,抽象工廠須要修改基類,工廠方法則是增長新的工廠子類。
  • 什麼時候使用

當咱們須要的不只僅是一個產品,而是一個包含了多個相關聯或相依存的不一樣產品結構的產品族,且咱們不想指定具體的類或者建立的細節。

  • Cocoa中的應用

最多見的就是NSNumberNSStringNSArrayNSDictionary。其中NSNumber中的numberWithBool:生成的實際類型是NSCFBoolean類型,而其餘的大多數生成的是NSCFNumber類型,而且都實現了抽象超類NSNumber的全部定義。這裏的NSCFBooleanNSCFNumber就至關於兩個工廠子類,超類的全部定義就至關於一系列產品,Fundation框架中抽象工廠的這種特色,被稱爲類簇

類簇是Fundation框架中的一種很是常見的設計模式,基於抽象工廠的思想。它將若干個私有具體工廠子類集合到一個公有的抽象超類之下。例如NSNumber有一系列公有API,定義了各類類型數據的共有行爲,咱們在使用時不用關心NSNumber實例的具體類型。

注:類簇中每每提供了許多生成工廠子類的方法,這些方法不該該在具體的工廠子類中重載,工廠子類只應該關注產品的建立。
複製代碼
  • 實際開發中的應用

例如前面說到的股票詳情,一旦詳情頁面的變得複雜,每每須要由多種界面元素來組成,而且隨着股票種類的增長,咱們可能並不想要在關注咱們用什麼具體的工廠子類去實例化詳情,這裏咱們就可使用抽象工廠。

能夠將詳情大體劃分爲四層:Nav信息層、基礎盤口層、圖表層和資訊層。定義一個抽象超類詳情TKHqStockDetailViewController,定義一系列基於這四層的公有API,而且聲明+ (TKHqStockDetailViewController *)detailWithStock:(TKHqStockModel *)stockModel的類工廠方法,該方法中經過股票類型建立了不一樣的「詳情工廠」,最終在各自的工廠子類中實現一系列的API。

適配器模式


適配器模式:將一個類的接口轉換成客戶但願的另一個接口。適配器模式使得原來因爲接口不兼容而不能一塊兒工做的那些類能夠一塊兒工做。

基本上有兩種實現適配器的方式:類適配器和對象適配器。

類適配器:經過多繼承來實現,在OC中能夠經過協議和單繼承模擬多繼承。協議用於規範統一的接口,父類用於實現具體的新接口,子類經過重載協議的目標接口,在接口內部調用父類的新接口來響應處理。

對象適配器:與類適配器不一樣,它不須要繼承被適配者,僅僅須要實現統一的協議,並持有一個被適配者的引用,在重載的協議接口中,調用該引用的新接口來響應處理。

兩種方式的區別以下:

  1. 類適配器只針對單一具體的被適配者,不適用於被適配者的子類,不然須要新建適配器;對象適配器能夠適配多個被適配者,若是要適配它們的子類,聲明一個子類引用便可。
  2. 類適配器易於重載被適配者的行爲,而對象適配器不能重載,不然須要新建被適配者的一個子類,再持有這個子類實例的引用。
  3. 類適配器無需使用額外的指針間接訪問被適配者,而對象適配器須要。
注:通常來講,對象適配器適用範圍更普遍,對於將來可能新增的須要適配的新接口,也更容易擴展。
複製代碼
  • 什麼時候使用對象適配器
  1. 已有類的接口與需求不匹配。
  2. 想要一個可複用的類,該類可以同可能帶有不兼容接口的其餘類協做。
  3. 須要適配一個類的幾個不一樣子類,但是讓每個子類去子類化一個類適配器又不現實。
  • 實際開發中的使用

例如詳情的設置頁面,咱們發現Cell的結構基本差很少,能夠由Title、SubTitle、Detail、AccessoryView四部分組成,其中某些Cell可能顯示SubTitle有的不顯示;有的顯示Detail有的不顯示;AccessoryView內容多是個箭頭,有的多是個SwitchBar。若是咱們對每種樣式去定製化一個Cell,無疑是難以維護和擴展的,這裏咱們就能夠經過適配器模式,將每種設置的數據適配成規範數據來統一處理。

咱們能夠建立一個Protocol來聲明目標接口,包括了Title、SubTitle、Detail、AccessoryView四部份內容,而後定義一個Adapter實現該協議,將使用到各類被適配者(在這裏也就是不一樣設置類型原來使用的Model)持有引用,而後目標接口中判斷哪一種引用不爲nil,而後根據當前被適配者的接口來獲取相應的數據,這樣外部在使用不一樣設置類型時,只須要將原來的Model傳給Adapter,Cell便能經過Adapter來獲取統一規範的數據。

注:也能夠經過實現Protocol 、集成各自Model的具體子類的類適配器方式來實現上述功能,這樣子Adapter中就只處理父類Model的數據,在使用時不一樣設置給Cell設置不一樣的子Adapter便可。
複製代碼

委託模式


委託模式:主要是適配器模式,它實際上一樣是把類的接口變換爲客戶端要求的另外一種接口,經過Protocol來要求其餘類適配它須要的接口,而它自己就是個適配器。

  • 什麼時候使用

當咱們須要其餘類來作一些當前類沒法完成的事情,或者須要使用者來處理某些個性化操做。 通常能夠經過delegate或者block來實現。

  • Cocoa中的使用

最多見的就是UITableView中delegate和datasource的使用,用來使用者自定義某些設置和響應事件。

  • 實際開發中的應用

例如須要傳遞上一層數據、須要使用者來定義某些設置、View須要VC來響應push/pop等等。

代理模式


代理模式:爲其餘對象提供一種代理以控制對這個對象的訪問。其思想是使用一個基本上跟實體對象行爲相同的代理。

  • 什麼時候使用
  1. 須要一個遠程代理,爲位於不一樣地址空間或網絡中的對象提供本地表明。
  2. 須要一個虛擬代理,來根據要求建立重型的對象。
  3. 須要一個保護代理,來根據不一樣訪問權限控制對原對象的訪問。
  4. 須要一個智能引用代理,經過對實體對象的引用進行計數來管理內存。也能用於鎖定實體對象,讓其餘對象不能修改它。
  • Cocoa中的應用

Objective-C中的delegate屬於委託模式,但也基於了代理模式的思想,如第四點所說,也至關於一個智能引用代理,同時經過協議接口的控制,也必定程度上至關於控制了對原對象的訪問權限。

  • 實際開發中的應用

NSProxy

橋接模式


橋接模式:將抽象部分與它的實現部分分離,使它們均可以獨立地變化。 通俗來說,若是實現系統可能有多角度分類,每一種分類都有可能變化,那麼就把這種多角度分離出來讓它們獨立變化,較少耦合。

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

觀察者模式


觀察者模式:定義對象間的一種一對多的依賴關係,當一個對象的狀態發生改變時,全部依賴於它的對象都獲得通知並被自動更新。也叫作發佈-訂閱模式。

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

有兩種技術都使用了觀察者模式:通知和KVO。

中介者模式


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

  • 什麼時候使用
  1. 對象間的交互雖定義明確然而很是複雜,致使一組對象彼此相互依賴並且難以理解。
  2. 由於對象應用了許多其餘對象並與其通信,致使對象難以複用。
  3. 想要定製一個分部在多個類中的邏輯或者行爲,又不想生成太多子類。
  • 實際開發中的使用

在多模塊的開發中,因爲不一樣產品模塊由不一樣小組開發,相互之間的代碼相對封閉,可是因爲業務關聯,每每又須要跟其餘模塊交互,好比A模塊打開B模塊頁面,B模塊又須要查詢C模塊的數據,通常實現可能直接A調用B模塊相關代碼,B模塊調用C模塊相關代碼,這樣形成的問題一是模塊之間相互耦合,獨立開發十分困難,須要屏蔽相關代碼;二是一旦其餘模塊的API修改,相關模塊全都得改動。

針對這個問題,可使用中介者模式,框架定義了一箇中介者基類baseMediator,並實現了一套協議用於接收外部事件,A模塊若是想要與B模塊交互,能夠經過一個通知方法告訴BMediator,而後BMediator根據不一樣參數來處理相應事件,這樣避免了模塊之間的強耦合,同時外部模塊也不在關心它的內部實現,只須要關心其暴露出來的事件定義。

相關文章
相關標籤/搜索