關於三者的比較說明,能夠看Casa醬的這篇iOS應用架構談 view層的組織和調用方案,巧神的被誤解的 MVC 和被神化的 MVVM篇幅有限,也能夠瞅一眼~html
原型模式:使用原型實例指定建立對象的種類,並經過複製這個原型建立新的對象。ios
它是一個很是簡單的設計模式,基於「複製」操做。複製指用同一模具生產一系列的產品。模具所基於的物品稱爲原型。 此模式的最低限度是生成對象的真實副本,以用做同一環境下其餘相關事物的基礎。設計模式
通俗來講,若是要建立的新對象和自身差別並不大,其行爲略有不一樣,且複製自身比手工實例化要好,就可使用原型模式。bash
例如我有一個Person
實例A,我須要一個跟A僅Name
不一樣,可是其他屬性均相同的新對象B,若是使用者經過新建實例並將A的全部屬性賦值給B,這無疑是至關麻煩的,這時咱們就可使用B = [A clone]
來複制A的屬性,從而節省大量精力,提升了複用性也便於維護。markdown
最多見的應用就是深複製,如NSMutableArray = [NSArray mutableCopy]
。網絡
注:淺複製不屬於原型模式,它不知足上面說到的原型模式的最低限度,僅僅是指針拷貝。
複製代碼
比較常見的狀況就是對自定義對象進行拷貝的時候,咱們須要經過對自定義對象實現NSCopying
協議及其方法- (id)copyWithZone:(NSZone *)zone
。多線程
單例模式:保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。它幾乎是全部設計模式中最簡單的一個了。架構
最多見的就是[UIApplication sharedApplication]
。mvc
例如一些管理類xxManager
,設置類xxConfiger
等等,都是會頻繁使用而且須要共享資源保存臨時狀態,就可使用單例。 關於多線程下加鎖保證只建立一個實例,咱們可使用@synchronized、NSLock等,更推薦使用dispatch_once,性能更優。 甚至咱們還可使用宏來實現單例。框架
因爲Objective-C並不能像C++,Java中同樣可以隱藏構造函數,小夥伴們仍是能夠alloc/init來建立對象,通常有兩種解決方案:
工廠方法模式:也叫作虛構造器。定義建立對象的接口,讓子類決定實例化哪個類。工廠方法使得一個類的實例化延遲到其子類。
通俗來說,對於有多種相似的產品,咱們能夠將產品的公有屬性和方法抽象爲一個產品基類,將生產產品的工廠抽象爲一個工廠基類,並暴露返回產品對象的工廠方法,各自產品的工廠繼承自工廠基類,並重載該工廠方法以返回對應的產品對象。
例如一開始的股票詳情界面,有指數、滬深、港股、美股等等,分別有一個基於TKHqBaseStockDetailViewController
的詳情子類,以及基於TKHqBaseStockDetailFactory
的工廠子類,工廠提供了一個建立詳情的方法,使用者可使用對應的工廠子類來獲取想要的詳情子類。
注:咱們也能夠經過傳遞股票信息在工廠內部經過枚舉來直接建立對應的詳情子類,而不經過工廠子類來建立,這種就是簡單工廠。
複製代碼
抽象工廠模式:提供一個建立一系列相關或相互依賴對象的接口,而無需指定它們具體的類。
通俗來說,咱們能夠提供一個工廠基類,其中包含了建立一系列產品的工廠方法,而且經過使用預處理或者枚舉來生成不一樣的工廠子類,這些工廠子類中都實現了基類的工廠方法,並根據本身的需求在創造產品的工廠方法中獲取想要的具體的產品子類。
當咱們須要的不只僅是一個產品,而是一個包含了多個相關聯或相依存的不一樣產品結構的產品族,且咱們不想指定具體的類或者建立的細節。
最多見的就是NSNumber
、NSString
、NSArray
及NSDictionary
。其中NSNumber
中的numberWithBool:
生成的實際類型是NSCFBoolean
類型,而其餘的大多數生成的是NSCFNumber
類型,而且都實現了抽象超類NSNumber
的全部定義。這裏的NSCFBoolean
和NSCFNumber
就至關於兩個工廠子類,超類的全部定義就至關於一系列產品,Fundation框架中抽象工廠的這種特色,被稱爲類簇。
類簇是Fundation框架中的一種很是常見的設計模式,基於抽象工廠的思想。它將若干個私有具體工廠子類集合到一個公有的抽象超類之下。例如NSNumber
有一系列公有API,定義了各類類型數據的共有行爲,咱們在使用時不用關心NSNumber
實例的具體類型。
注:類簇中每每提供了許多生成工廠子類的方法,這些方法不該該在具體的工廠子類中重載,工廠子類只應該關注產品的建立。
複製代碼
例如前面說到的股票詳情,一旦詳情頁面的變得複雜,每每須要由多種界面元素來組成,而且隨着股票種類的增長,咱們可能並不想要在關注咱們用什麼具體的工廠子類去實例化詳情,這裏咱們就可使用抽象工廠。
能夠將詳情大體劃分爲四層:Nav信息層、基礎盤口層、圖表層和資訊層。定義一個抽象超類詳情TKHqStockDetailViewController
,定義一系列基於這四層的公有API,而且聲明+ (TKHqStockDetailViewController *)detailWithStock:(TKHqStockModel *)stockModel
的類工廠方法,該方法中經過股票類型建立了不一樣的「詳情工廠」,最終在各自的工廠子類中實現一系列的API。
適配器模式:將一個類的接口轉換成客戶但願的另一個接口。適配器模式使得原來因爲接口不兼容而不能一塊兒工做的那些類能夠一塊兒工做。
基本上有兩種實現適配器的方式:類適配器和對象適配器。
類適配器:經過多繼承來實現,在OC中能夠經過協議和單繼承模擬多繼承。協議用於規範統一的接口,父類用於實現具體的新接口,子類經過重載協議的目標接口,在接口內部調用父類的新接口來響應處理。
對象適配器:與類適配器不一樣,它不須要繼承被適配者,僅僅須要實現統一的協議,並持有一個被適配者的引用,在重載的協議接口中,調用該引用的新接口來響應處理。
兩種方式的區別以下:
注:通常來講,對象適配器適用範圍更普遍,對於將來可能新增的須要適配的新接口,也更容易擴展。
複製代碼
例如詳情的設置頁面,咱們發現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來實現。
最多見的就是UITableView中delegate和datasource的使用,用來使用者自定義某些設置和響應事件。
例如須要傳遞上一層數據、須要使用者來定義某些設置、View須要VC來響應push/pop等等。
代理模式:爲其餘對象提供一種代理以控制對這個對象的訪問。其思想是使用一個基本上跟實體對象行爲相同的代理。
Objective-C中的delegate屬於委託模式,但也基於了代理模式的思想,如第四點所說,也至關於一個智能引用代理,同時經過協議接口的控制,也必定程度上至關於控制了對原對象的訪問權限。
NSProxy
橋接模式:將抽象部分與它的實現部分分離,使它們均可以獨立地變化。 通俗來說,若是實現系統可能有多角度分類,每一種分類都有可能變化,那麼就把這種多角度分離出來讓它們獨立變化,較少耦合。
觀察者模式:定義對象間的一種一對多的依賴關係,當一個對象的狀態發生改變時,全部依賴於它的對象都獲得通知並被自動更新。也叫作發佈-訂閱模式。
有兩種技術都使用了觀察者模式:通知和KVO。
中介者模式:用一個對象來封裝一系列對象的交互方式。中介者使各對象不須要顯示地相互引用,從而使其耦合鬆散,並且能夠獨立地改變它們之間的交互。
在多模塊的開發中,因爲不一樣產品模塊由不一樣小組開發,相互之間的代碼相對封閉,可是因爲業務關聯,每每又須要跟其餘模塊交互,好比A模塊打開B模塊頁面,B模塊又須要查詢C模塊的數據,通常實現可能直接A調用B模塊相關代碼,B模塊調用C模塊相關代碼,這樣形成的問題一是模塊之間相互耦合,獨立開發十分困難,須要屏蔽相關代碼;二是一旦其餘模塊的API修改,相關模塊全都得改動。
針對這個問題,可使用中介者模式,框架定義了一箇中介者基類baseMediator
,並實現了一套協議用於接收外部事件,A模塊若是想要與B模塊交互,能夠經過一個通知方法告訴BMediator
,而後BMediator
根據不一樣參數來處理相應事件,這樣避免了模塊之間的強耦合,同時外部模塊也不在關心它的內部實現,只須要關心其暴露出來的事件定義。