日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

Cocoa设计模式(iOS常用设计模式) Cocoa Design Patterns

發布時間:2023/12/16 asp.net 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Cocoa设计模式(iOS常用设计模式) Cocoa Design Patterns 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Cocoa設計模式

Cocoa環境的許多架構和機制都能夠有效地使用設計模式:抽象設計可以解決特定環境中的重復問題。 本文描述了Cocoa中設計模式的主要實現,主要關注模型(Model) - 視圖(View) - 控制器(Controller)和對象建模。 本章的主要目的是讓您更深入地了解Cocoa的設計模式,并鼓勵您在自己的軟件項目中利用這些模式。

什么是設計模式?

設計模式是設計的模板,它可以在特定的上下文中解決一般的、重復出現的問題。它是一種抽象工具,在建筑、工程和軟件開發等領域都很有用。下面的部分總結了設計模式是什么,解釋了為什么它們對于面向對象設計很重要,并討論了一個示例設計模式。

一個問題的解決方案

作為開發人員,您可能已經熟悉面向對象編程中的設計模式概念。 他們首先由Erich Gamma,Richard Helm,Ralph Johnson和John Vlissides(通常被稱為“四人幫”)設計模式:可重用面向對象軟件的元素進行了權威性的描述和編目。 這本書最初發表于1994年,不久之后還有其他書籍和文章,進一步探討和闡述了面向對象系統中的設計模式。

設計模式的簡潔定義是“對上下文中的問題的解決方案”。讓我們通過反向解釋這個短語來解析這個問題。 上下文是該模式適用的反復出現的情況。 問題是你在這個上下文中試圖達到的目標,以及上下文所帶來的任何約束。 解決方案就是你所追求的目標:通用的上下文設計,達到目標并解決約束。

設計模式將具體設計結構的關鍵方面抽象出來,這已經被證明是有效的。 該模式有一個名稱,并標識參與該模式的類和對象及其職責和協作。 它還列出了后果(成本和收益)以及該模式可以應用的情況。 設計模式是特定設計的一種模板或指南; 從某種意義上講,具體的設計就是一種模式的“實例化”。 設計模式并不是絕對的。 在如何應用它們方面有一定的靈活性,通常諸如編程語言和現有體系結構的東西可以決定如何應用模式。

設計的幾個主題或原則影響設計模式。 這些 設計原則是構建面向對象系統的經驗法則,如“封裝不同系統結構的各個方面”,“編程是為了接口而不是實現”,它們表達了重要的見解。 例如,如果您隔離系統中各部分并將其封裝起來,那么它們可以獨立于系統的其他部分而變化,特別是如果您為它們定義了與實現細節無關的接口。 您稍后可以更改或擴展這些可變部分,而不會影響系統的其他部分。 因此,您可以消除依賴性并減少部件之間的耦合,從而使系統變得更加靈活和易于更改。

在編寫軟件時,設計模式是一個重要的考慮因素。 如果您在程序設計中找到,適應和使用模式,那么程序(包括它所包含的對象和類)將更具可重用性,可擴展性和更容易隨著未來需求的變化而改變。 而且,基于設計模式的程序通常比不考慮設計模式的程序更加優雅和高效,因為它們只需要更少的代碼就能實現相同的目標。

舉例:命令模式(Command Pattern)

“四人幫”的大部分書籍都是由一個設計模式目錄組成的。 它按范圍(類或對象)和目的(創建,結構或行為)對目錄中的模式進行分類。 目錄中的每個條目討論設計模式的意圖,動機,適用性,結構,參與者,合作,后果和實現。 其中一個條目是 命令模式(一種對象行為模式)。

本書陳述Command模式的意圖是“將請求封裝為一個對象,從而允許您使用不同的請求參數化客戶端,排隊或記錄請求,并支持可撤銷操作”。模式將發送消息的對象與接收和評估這些消息的對象分隔開。 消息的發起者(客戶端)通過將特定接收者上的一個或多個動作綁定在一起來封裝請求。 封裝的消息可以在對象之間傳遞,放置在隊列中或以其他方式存儲以用于稍后的調用,并且動態地修改以改變接收器或消息參數。 下圖顯示了該模式的結構圖。

對于一個熟悉Cocoa的開發者來說,命令模式的這個簡短的概述可能會敲響一個鐘聲。 該模式完美地描述了Foundation框架中的一個類,其目的是封裝消息: NSInvocation。 正如該模式的意圖狀態,其目的之一是使操作可撤銷。 調用對象用于Cocoa設計中 撤銷管理以及分布式對象,這是一個進程間通信的體系結構。 命令模式也描述(雖然不太完美)Cocoa的target-action機制,其中用戶界面控制對象封裝了用戶激活時發送的消息的目標和動作。

在其框架類,語言和runtime,Cocoa已經為您實現了很多編目設計模式。 (這些實現在下面有描述。)通過使用設計模式的“現成”適應性,可以滿足您的許多開發需求。 或者你可以根據你的問題,它的上下文來需要一個你自己的全新的基于模式的設計。 重要的是在開發軟件時要有意識的注意模式,并在適當的時候在設計中使用它們。

Cocoa如何改變設計模式

可以在OS X和iOS版本中找到適用于Cocoa的設計模式。 基于模式的機制和體系結構在Cocoa框架和Objective-C 的 runtime 和語言中很常見。 Cocoa經常把自己獨特的旋律放在一個模式上,因為它的設計受語言能力或現有體系結構等因素的影響。

本節包含大多數設計模式的摘要,這些設計模式是在“ 設計模式:可重用面向對象軟件的元素”中編目的。 每個部分不僅總結了模式,還討論了Cocoa的實現。 只列出Cocoa實現的模式,以下各節中的模式描述都與特定的Cocoa上下文有關。

Cocoa設計模式的實現有多種形式。 以下部分中描述的一些設計(如協議和類別)是 Objective-C語言的特性。 在一些情況下,“模式實例”是在一個類或一組相關類(例如,類集群和單例類)中實現的。 在另一些情況下,模式適應是一個主要的框架體系結構,例如響應者鏈。 一些基于模式的機制幾乎可以“免費”獲得,而另外一些機制則需要做一些工作。 即使Cocoa沒有實現一個模式,當情況需要時,你自己可以這樣實現; 例如,對象組合(Decorator模式)通常比繼承類的行為更好。

兩個設計模式保留給后面的部分,模型 - 視圖 - 控制器(MVC)和對象建模。 MVC是一種復合或聚合模式,這意味著它基于幾種目錄模式。 對象建模在“四人幫”目錄中沒有對應,而是源于關系數據庫的領域。 然而MVC和對象建模也許是Cocoa中最重要,最普遍的設計模式,在很大程度上它們是相互關聯的模式。 它們在包括綁定,撤銷管理,腳本和文檔體系結構在內的多種技術的設計中起著至關重要的作用。

抽象工廠(Abstract Factory)

抽象工廠模式提供了一個接口,用于創建相關或依賴對象的族,而不指定具體的類。 客戶與從工廠獲得的具體對象的任何具體細節分離。

類集群

類集群是一種將公共抽象父類下的許多私有具體子類組織在一起的體系結構。 抽象父類聲明了創建其私有子類實例的方法。 父類根據調用的創建方法分配適當的具體子類的對象。 每個返回的對象可能屬于不同的私有具體子類。

Cocoa中的類集群只能生成其數據存儲可能因環境而異的對象。 Foundation框架具有NSString ,NSData, NSDictionary,NSSet和NSArray對象的類集群。 公共父類包括這些不可變類以及互補的可變類NSMutableString , NSMutableData ,NSMutableDictionary , NSMutableSet和NSMutableArray。

使用和限制

如果要創建集群表示類型的不可變或可變對象,則可以使用類集群的公共類之一。 對于類集群,在簡單性和可擴展性之間進行權衡。 一個類集群簡化了一個類的接口,從而更容易學習和使用這個類。 但是,創建類集群的抽象父類的自定義子類通常比較困難。

適配器

適配器設計模式將類的接口轉換為客戶期望的另一個接口。 適配器讓類能夠協同工作。 它將客戶從目標對象的類中分離出來。

協議 (Protocols)

一個 協議是一種語言級(Objective-C)功能,可以定義適配器模式實例的接口。 協議本質上是一系列與類無關的方法聲明。 (在Java中, 接口與協議是同義的)。如果你想要一個客戶端對象與另一個對象進行通信,但是對象的不兼容接口使得這個接口變得困難,你可以定義一個協議。 另一個對象的類然后正式采用該協議,并通過實現該協議的一個或多個方法來“符合”該協議。 該協議可能要求符合類實現其一些方法,并可能使其他的實現可選。 然后客戶端對象可以通過協議接口將消息發送到另一個對象。

協議創建了一組獨立于類層次結構的方法聲明。 它們可以在協議一致性和類繼承的基礎上對對象進行分組。 NSObject方法 conformsToProtocol:允許您驗證對象的協議從屬關系。

Cocoa有非正式協議以及正式協議。 非正式協議是NSObject類中的一個類別,因此可以使任何對象成為該類別中任何方法的潛在實現者。 非正式協議中的方法可以有選擇地實現。 非正式協議是OS X中委托機制實施的一部分。

請注意,協議的設計并不完全匹配適配器模式的描述。 但是它實現了這個模式的目標:允許具有不兼容接口的類一起工作。

使用和限制

您主要使用一個協議來聲明一個接口,如果他們想要進行通信,那么層次上無關的類將被預期符合。 但是你也可以使用協議來聲明一個對象的接口,同時隱藏它的類。 Cocoa框架包括許多正式的協議,使定制的子類能夠與特定的目的進行通信。 例如,Foundation框架包含NSObject,NSCopying和NSCoding協議,這些協議都非常重要。 AppKit協議包括 NSDraggingInfo , NSTextInput ,和 NSChangeSpelling。 UIKit協議包括 UITextInputTraits , UIWebViewDelegate ,和 UITableViewDataSource 。

正式的協議隱式地要求符合類來實現所有聲明的方法。 但是,他們可以用@optional指令標記單個方法或方法組,并且符合類可以選擇執行這些方法。 他們也很脆弱; 一旦你定義了一個協議并使其可用于其他類,將來對其進行的更改(除了附加的可選方法外)可能會破壞這些類。

責任鏈

責任鏈設計模式通過給予多個對象一個機會來處理請求,從而將請求的發送者與其接收者分離。 該模式將接收對象鏈接在一起,并沿著鏈傳遞請求,直到對象處理它為止。 鏈中的每個對象處理請求或將其傳遞給鏈中的下一個對象。

響應者鏈

應用程序框架包括稱為響應者鏈的體系結構。 這個鏈由一系列響應者對象組成(也就是繼承對象) NSResponder 或者,在UIKit中, UIResponder ),一個事件(例如,一個鼠標點擊)或動作消息被傳遞(通常)最終被處理。 如果給定的響應者對象不處理特定的消息,則將消息傳遞給鏈中的下一個響應者。 響應者對象在鏈中的順序通常由視圖層次結構決定,從層次結構中的低級響應者到高層響應者的進程,最終在管理視圖層次的窗口對象,窗口對象的委托,或全局應用程序對象。 響應者鏈上的事件和行動消息的路徑是不同的。 應用程序可以擁有盡可能多的響應者鏈,因為它具有窗口(甚至是本地層次的視圖)。 但是一次只能有一個響應者鏈,即與當前活動窗口關聯的響應者鏈。

AppKit框架對錯誤處理也實現了類似的響應鏈。

iOS注意: UIKit實現的響應者鏈不同于AppKit。 如果一個視圖是由一個 UIViewController 對象,視圖控制器成為鏈中的下一個響應者(從那里事件或動作消息傳遞到視圖的超級視圖)。 另外,UIKit本身不支持文檔體系結構; 因此響應者鏈中沒有文檔對象或窗口控制器對象。 iOS中也沒有錯誤處理應答鏈。

視圖層次結構與響應者鏈緊密相關,調整復合模式的設計 。 動作消息(來自控制對象的消息)基于target-action機制,它是命令模式的一個實例。

使用和限制

當您使用Interface Builder或以編程方式為程序構建用戶界面時,您可以免費獲得一個或多個響應者鏈。響應者鏈與視圖層次結構緊密相關,您在創建視圖時會自動獲取對象窗口的內容視圖的子視圖。 如果您將自定義視圖添加到視圖層次結構中,它將成為響應者鏈的一部分。 如果您實施適當的NSResponder或UIResponder方法,則可以接收和處理事件和操作消息。 作為窗口對象或全局應用程序對象的委托的自定義對象(AppKit中的NSApp )也可以接收和處理這些消息。

您也可以通過編程方式將自定義響應者注入到響應者鏈中,并且可以通過編程方式操縱響應者的順序。

命令

命令設計模式將請求作為對象進行封裝,從而使您可以使用不同請求參數化客戶端,排隊或記錄請求,并支持可撤銷操作。 請求對象將特定接收者上的一個或多個動作綁定在一起。 命令模式將發出請求的對象與接收和執行該請求的對象分開。

調用對象

一個實例 NSInvocation 類封裝了一個 Objective-C消息。 一個調用對象包含一個目標對象,方法選擇器和方法參數。 您可以動態地更改調用對象調度的消息的目標及其參數; 一旦調用被執行,您也可以從對象中獲取返回值。 使用單個調用對象,您可以重復調用目標和參數具有多種變化的消息。

創建一個NSInvocation對象需要一個NSMethodSignature對象,它是一個封裝了與方法的參數和返回值有關的類型信息的對象。 NSMethodSignature對象又是從方法選擇器創建的。 NSInvocation的實現也利用了Objective-C runtime 的功能。

使用和限制

NSInvocation對象是分布式對象的編程接口,撤銷管理,消息轉發和定時器的一部分。 您還可以在類似的上下文中使用調用對象,您需要從接收消息的對象中分離發送消息的對象。

分布式對象技術用于進程間通信。

Target-Action 機制

該 target-action機制使控件對象(即按鈕,滑塊或文本字段等對象)能夠將消息發送到另一個可以解釋消息并將其作為特定于應用程序的指令處理的對象。 接收對象,或者 目標,通常是一個自定義控制器對象。 消息命名為 動作消息 - 由選擇器確定,一個方法的唯一運行時標識符。

在AppKit框架中,控件擁有的單元對象通常封裝了目標和動作。 當用戶點擊或以其他方式激活控件時,控件從其單元中提取信息并發送消息。 (菜單項還封裝了目標和動作,并在用戶選擇時發送一個動作消息。)目標動作機制可以基于選擇器(而不是方法簽名)工作,因為動作方法的簽名在按照慣例AppKit總是相同的。

在UIKit中,目標操作機制不依賴于單元格。 相反,控件會將目標和操作映射到控件上可能發生的一個或多個多點觸控事件。

使用和限制

創建Cocoa應用程序時,可以通過Interface Builder應用程序設置控件的操作和目標。 因此,您可以讓控件啟動自定義行為,而無需為控件本身編寫任何代碼。 動作選擇器和目標連接存檔在nib文件中,并在nib被取消存檔時恢復。 您也可以通過發送控件或其單元格setTarget:和setAction: messages來動態更改目標和動作。

用于OS X的Cocoa應用程序可以使用目標操作機制來指示自定義控制器對象將數據從用戶界面傳輸到模型對象,或者在模型對象中顯示數據。 Cocoa綁定技術避免了為此目的使用目標動作的需要。 看到 可可綁定編程主題 關于這項技術的更多信息。

Controls和cell不保留其目標。

復合

復合設計模式將相關對象組合成樹結構來表示部分 - 整體層次結構。 該模式可以讓客戶統一處理個別對象和對象組合。

Composite模式是Model-View-Controller聚合模式的一部分

查看層次結構

View ( NSView 要么 UIView 對象)在一個窗口內部結構化成一個 視圖層次。 在層次結構的根部是一個窗口( NSWindow 要么 UIWindow 對象)及其內容視圖,一個透明視圖,填充窗口的內容矩形。 添加到內容視圖中的視圖成為其子視圖,并成為添加到視圖中的所有視圖的超級視圖。 除了內容視圖外,視圖還有一個(也是唯一的) superview和零或任何數量的 子視圖。 你認為這個結構是遏制:父視圖包含它的子視圖。 圖4-2顯示了視圖層次結構的視覺和結構方面。

視圖層次結構是在繪圖和事件處理中起作用的結構體系結構。 一個視圖有兩個邊界矩形,它的框架和邊界,這些矩形會影響視圖的圖形操作。 框架是外部邊界; 它將視圖定位在其超級視圖的坐標系中,定義其大小,并將繪圖剪輯到視圖的邊緣。 邊界(內部邊界矩形)定義視圖自身繪制的曲面的內部坐標系。

當窗口系統要求窗口準備顯示時,要求超級視圖在其子視圖之前進行渲染。 當你發送一些消息到一個視圖 - 例如,一個請求視圖重繪自己的消息 - 消息傳播到子視圖。 因此,您可以將視圖層次結構的分支視為統一的視圖。

響應者鏈也使用視圖層次來處理事件和動作消息。

使用和限制

無論是以編程方式還是使用Interface Builder將視圖添加到其他視圖,都可以創建或修改視圖層次結構。 AppKit框架自動處理與視圖層次關聯的所有關系。

裝飾器

裝飾設計模式動態地將額外的責任附加到對象上。 裝飾器為擴展功能提供了子類化的靈活替代方案。 與子類化一樣,修飾器模式的適應性允許您在不修改現有代碼的情況下合并新的行為。 裝飾器包裝了它們擴展行為的類的一個對象。 它們實現與它們所包裝的對象相同的接口,并在將任務委托給包裝對象之前或之后添加它們自己的行為。 Decorator模式表達了這樣的設計原則:類應該是可以拓展的,而不需要修改類。

常規注釋

裝飾者是一個對象組合模式,非常鼓勵這樣做。 但是,Cocoa提供了一些自己的類和機制(在下面的部分討論)是基于裝飾模式。 在這些實現中,擴展對象并不完全復制它所包裝的對象的接口,并且這些實現使用不同的技術來進行接口共享。

Cocoa在其幾個類的實現中使用了Decorator模式,包括NSAttributedString ,NSScrollView ,和 UIDatePicker 。 后兩個類是復合視圖的例子,它將其他視圖類的簡單對象組合在一起,并協調它們的交互。

代理 (Delegation)

代理是一種機制,通過這種機制,宿主對象將一個弱引用(意味著它是一個簡單的指針引用,而不是 retained)嵌入到另一個對象中,在需要輸入任務時定期向代理發送消息。 宿主對象通常是一個“現成的”框架對象(比如 NSWindow 要么 NSXMLParser 對象)正在尋求完成一些事情,但只能以一種通用的方式來實現。 代理幾乎總是一個自定義類的實例,與主機對象協調工作,在任務的某些點提供程序特定的行為( 見下圖 )。 因此,委派可以修改或擴展另一個對象的行為,而無需進行子類化。

代理,就一個對象委托給另一個對象的簡單意義而言,是面向對象編程中的常用技術。 然而,Cocoa以一種獨特的方式實現了代理。 一個主機類使用一個 正式協議或一個 非正式協議來定義委托對象可以選擇實現的接口。 非正式協議中的所有方法都是可選的,正式的協議可以聲明可選的方法,允許委托只實現協議中的一些方法。 在嘗試向其委托發送消息之前,主機對象決定是否實現該方法(通過respondsToSelector:消息)以避免運行時異常。

Cocoa框架中的一些類也向它們的數據源發送消息。 數據源在所有方面都與代理相同,除了意圖是向主機對象提供數據以填充瀏覽器,表視圖或類似的用戶界面視圖。 與委托人不同,數據源也可能需要實現協議的某些方法。

代理不是Decorator模式的嚴格實現。 主機(delegating)對象不包裝它想要擴展的類的一個實例; 事實上,這是另一回事,委托人正在專門委托框架類的行為。 除了由框架類聲明的代理方法,也沒有接口的共享。

Cocoa的代理也是模板方法模式的一部分。

使用和限制

代理是Cocoa框架中的一個常見設計。 AppKit和UIKit框架中的許多類將消息發送給代理,包括 NSApplication , UIApplication , UITableView ,和幾個子類 NSView 。 Foundation框架中的一些類,例如NSXMLParser和 NSStream ,也維護代理。 除非委托方法不允許您實現您的目標,否則應始終使用類的代理機制,而不是繼承類的子類。

盡管可以動態更改代理,但一次只能有一個對象成為代理。 因此,如果您希望多個對象同時通知特定的程序事件,則不能使用代理。 但是,您可以為此使用通知機制。 只要委托實現框架類聲明的一個或多個通知方法,代理就會自動從其委托框架對象接收通知。

在AppKit中代理對象不保留代理或數據源。

分類(Categories)

一個 category是Objective-C語言的一個特性,它使您能夠將方法(接口和實現)添加到類中,而無需創建子類。 在程序范圍內,類的原始方法和類別添加的方法之間沒有運行時差異。 類別中的方法成為類類型的一部分,并由所有類的子類繼承。

和代理一樣,類別并不是對裝飾者模式的嚴格適應,實現了意圖,而是采取了不同的途徑來實現這個意圖。 按類別添加的行為是編譯時工件,并不是動態獲取的。 而且,類別不會封裝正在擴展的類的一個實例。

使用和限制

Cocoa框架定義了許多類別,其中大多數是非正式的協議。 他們經常使用類別來分組相關的方法。 您可以在您的代碼中實現類別來擴展不帶子類的類或將相關方法分組。 但是,你應該知道這些警告:

  • 不能將實例變量添加到類中。
  • 如果您覆蓋了該類的現有方法,那么您的應用程序可能會表現出不可預測性。

外觀(Facade)

外觀設計模式為子系統中的一組接口提供統一的接口。 該模式定義了一個更高層次的接口,通過降低復雜度并隱藏子系統之間的通信和依賴關系,使子系統更易于使用。

NSImage

NSImage 類 ,AppKit框架提供一個統一的接口用于裝載和使用圖像,可以是基于位圖(例如在JPEG,PNG,TIFF或格式)或基于向量的(例如在EPS或PDF格式)。NSImage可以保持相同的圖像的一個以上表示;每個表示是一種 NSImageRep 對象。 NSImage自動化選擇一種表現,對于一個特定類型的數據和對于給定的顯示裝置是合適的。它也隱藏了圖像操作和選擇的細節,使客戶可以互換使用許多不同的底層表示。

用途和限制

由于NSImage支持的圖像就是幾個不同的表現,一些請求的屬性可能不適用。例如,以像素的顏色請求圖像,如果底層圖像表示是基于矢量和設備無關,則不起作用。

迭代器

Iterator設計模式提供了一種方法來順序訪問聚合對象的(即,集合)元件,而不暴露其底層表示。迭代器模式轉換用于訪問和遍歷從集合本身集合的元素添加到迭代器對象的責任。迭代器定義了一個接口,用于訪問集合元素和跟蹤當前的元素。不同的迭代器可以執行不同的遍歷策略。

枚舉器

Foundation框架的NSEnumerator類實現了迭代器模式。抽象NSEnumerator類的私人、具體的子類返回枚舉對象,順序返回集合中的對象給客戶,有各種類型-數組,集合,詞典(值和鍵)。

NSDirectoryEnumerator是遠親類。這個類的實例遞歸枚舉在文件系統中目錄的內容。

用途和限制

集合類如NSArray,NSSet,和NSDictionary包括返回適當集合類型的枚舉方法。所有枚舉器以相同的方式工作。發送nextObject消息,當退出循環時,枚舉器對象nil返回,而不是集合中的下一個對象。

您還可以使用快速列舉訪問集合中的元素; 這種語言功能是快速枚舉。

中介者模式(Mediator)

中介者模式定義了如何封裝一組互動對象的對象。中介者促進由稱呼對方明確地保持對象的松散耦合,并可以獨立地改變它們之間的相互作用。因此,這些對象可以保持更多的重用。

此模式的一個“中介對象”集中在一個系統中對象之間復雜的通信和控制邏輯。這些對象告訴中介對象當其狀態的變化,反過來,從介體對象請求作出響應。

AppKit框架控制器類

模型 - 視圖 - 控制器設計模式給在一個面向對象的系統(例如應用)中的對象分配角色。它們可以是模型對象,其中包含應用程序的數據和操作這些數據; 它們可以是view對象,可以顯示數據和響應用戶的動作; 或者它們可以是控制器對象,作為所述模型和視圖對象之間的中介。控制器對象適合中介者模式。

在Cocoa中,控制器對象可以是兩種通用的類型: 中介控制器或 協調控制器。中介調解的控制器查看對象和模型對象之間的數據在應用程序的流程。中介控制器通常是NSController對象。協調控制器執行集中通信和控制邏輯用于應用,作為代理對框架對象和作為行動的消息的目標。他們是典型的NSWindowController對象或自定義NSObject對象子類。因為他們是如此高度專業化的特定程序,以協調控制器往往不被重用。

抽象類NSController和AppKit框架中它的具體子類是Cocoa綁定技術的一部分,它會自動同步包含在模型對象和顯示和查看對象編輯的數據的一部分。例如,如果用戶在text field編輯字符串,綁定技術傳達變化,通過一個中介控制器到綁定模型對象的相應屬性。所有的程序員需要做的就是正確設計自己的模型對象,并使用Interface Builder,建立一個程序的視圖,控制器,和模型對象之間的綁定。

Interface Builder庫中具體的公共控制器類的實例是可用的,因此是高度可重用。他們提供的服務,如選擇和占位符值的管理。這些對象執行以下具體功能:

  • NSObjectController 管理一個模型對象。
  • NSArrayController管理模型對象的數組,并保持一個選擇; 它也可以讓你的對象從array中添加和刪除對象。
  • NSTreeController 使您能夠以分層樹結構中添加,刪除和管理模型對象。
  • NSUserDefaultsController提供了一個方便的接口首選項(用戶缺省值)系統。
用途和限制

通常使用NSController的對象作為中介控制器,因為這些對象是為了應用程序查看對象和模型對象之間的通信數據來設計的。要使用中介控制器,您通常從Interface Builder的庫拖動對象,指定模型對象的屬性鍵,并建立使用Interface Builder的信息窗口的綁定窗格視圖和模型對象之間的綁定。您也可以繼承NSController或它的一個子類來獲得更專業的行為。

可以在任何一對對象之間都建立綁定,只要這些對象遵守NSKeyValueCoding和NSKeyValueObserving非正式協議。但為了NSController的優勢,最好是通過中介控制器進行綁定。

協調控制器集中應用程序的通信和控制邏輯:

  • 維護outlets模型和視圖對象(outlets是保持連接或引用其他對象的實例變量)
  • 通過目標-動作響應view對象的用戶操縱
  • 作為一個代理由框架對象發送的消息

通常做上述所有的連接,outlets,target-action,delegates,在Interface Builder,他們存檔在應用程序的nib文件。

View Controllers in UIKit

iOS中運行的應用程序經常使用一個模型和導航用戶界面的設計,用于呈現屏幕上的應用數據模型。一個應用程序可以具有導航欄和工具欄,這些對象之間的是應用數據的當前視圖。用戶可以點擊工具欄上的按鈕來選擇一個模式,導航欄上的點擊按鈕,并且在當前視圖點擊控制遍歷模型(數據)對象的層次結構;每個級別上的中央視圖顯示更多的細節。在這個層次的結尾往往是用戶可以檢查或編輯的項目。

從UIViewController繼承的視圖控制器。UIViewController是一個抽象類,可以繼承管理特定視圖。UIKit框架還提供用于管理導航欄和工具欄對象子類: UINavigationController 和 UITabBarController。如下圖所示,一個tab-bar控制器可以管理許多導航控制器,這反過來又可以管理一個或多個視圖控制器,每個具有其相關聯的view對象的步驟。除了管理視圖(包括重疊視圖),一個視圖控制器指定了顯示在導航欄中的按鈕和標題。

備忘錄模式(Memento)

備忘錄模式捕捉和外部化對象的內部狀態,而不違反封裝-使得對象可以恢復到這種狀態后。備忘錄模式保持關鍵對象外部的重要狀態。

歸檔

將對象存檔在一個程序中,隨著這些對象的屬性(屬性和關系)到檔案,可以存儲在文件系統或過程或在網絡之間傳輸。以字節存檔了一個程序的對象圖,保留對象的身份和他們之間的關系的一種體系結構無關的流。因為一個對象的類型及其數據存儲對象解碼字節流通常實例化的對象使用原來的編碼相同的類。

使用和限制

一般來說,你想保存一些程序中想要保存狀態的對象。模型對象幾乎都屬于這一類。寫一個對象的檔案進行編碼和解碼,通過解碼從歸檔中讀取那個對象。編碼和解碼是你使用NSCoder對象執行的操作,最好使用密鑰歸檔技術(你要調用的方法NSKeyedArchiver和NSKeyedUnarchiver類)。被編碼和解碼的對象必須符合NSCoding協議;該協議的方法被調用時歸檔

屬性列表序列化

屬性列表是一個簡單的,使用下面類對象結構序列化的對象圖:NSDictionary, NSArray, NSString, NSData,NSDate, NSNumber.這些對象通常被稱為屬性列表對象。幾個Cocoa框架類提供的方法來將這些屬性列表對象和定義數據流記錄的對象及其層次關系的特殊格式的內容。這個NSPropertyListSerialization類提供的類方法,可以從XML格式或優化的二進制格式,序列化屬性列表對象。

使用和限制

如果在對象圖中的對象是簡單的,屬性列表序列化是一個靈活的,便攜的,和足夠的手段來捕捉和呈現對象及其狀態。然而,這種形式的序列化有其局限性。它不保存對象完整的標識,只是一般的類型(數組,字典,字符串,等等)。因此,一個對象從屬性列表恢復可能是一個與原來類不同的類。這是一個問題,當一個對象的可變性可以不同。屬性列表序列化也不跟蹤,對象中多次引用的對象,可能會導致多個實例在反序列化,在原來的對象圖的一個實例。

Core Data

Core Data是Cocoa框架,定義了管理對象圖,使他們持續的架構。正是這第二能力對象持久化使Core Data適應備忘錄模式。

核心數據的設計也嚴重的影響了模型-視圖-控制器和對象建模模式。

使用和限制

Core Data在企業應用的發開中非常有用,模型對象的復雜圖必須定義,管理,和透明的歸檔和未歸檔和數據存儲。
核心數據是特別有用的企業應用中的模型對象的復雜圖必須定義,管理,和透明的歸檔和未歸檔和數據存儲。Xcode開發環境包括項目模板和設計工具,來減少需要創建核心數據應用的兩種類型的編程工作,那些基于文檔和那些不是基于文檔的數據。Interface Builder應用還包括可配置的庫中的核心數據結構對象。

觀察者(Observer)

觀察者設計模式定義了對象之間的一對多的依賴關系,當一個對象的狀態發生改變時,所有依賴于它的通知并自動更新。觀察者模式本質上是一個發布和訂閱模型,它的主體及其觀察員是松散耦合。觀察和觀察對象之間不需要知道對方就可以發生通信。

通知(Notifications)

Cocoa通知機制實現了一個基于觀察者模式的消息一對多廣播。在一個程序中的對象添加自己或其他對象的列表,有一個或多個通知觀察者,其中每一個是由全局的字符串識別(通知的名字)。要通知其它對象,觀察對象創建一個通知對象和推送到通知中心的對象。通知中心決定一個特定的通知觀察者,通過消息將通知發送到他們。該方法通過通知消息調用必須符合一定的單參數簽名。該方法的參數是通知對象,其中包含通知名,觀察對象,和一個包含任何補充信息字典。

推送通知是一個同步程序。發布對象不重新控制到通知中心有廣播通知所有的觀察者。對于異步行為,你可以在通知隊列中通知;控制立即返回到發布對象,當通知到達隊列頂部時通知中心再廣播。

定期通知,這些通過通知中心的廣播只是進程內。如果你想給其他進程廣播通知,您可以使用分布式通知中心及其相關的API。

使用和限制

你可以因為各種各樣的原因使用通知,。例如,可以廣播通知改變用戶界面元素的顯示信息,基于在程序的其他地方的某一事件。或者你可以用通知的方式確保目標文檔中的文檔窗口關閉前保存它們的狀態。通知的目的是告知其他對象程序事件使他們能夠作出適當的反應。

但對象接收通知的反應只有在已經發生的事件。這是和代理的顯著差異。代理有機會拒絕或修改由委托對象提出的操作。另一方面,觀察對象不能直接影響即將進行的操作。

通知類都是NSNotification(通知對象),NSNotificationCenter(推送通知和添加觀察員),NSNotificationQueue(隊列化通知),和NSDistributedNotificationCenter。許多Cocoa框架類發布通知后,任何對象都可以觀察。

Key-Value Observing

KVO是一種機制,允許當其他對象的具體特性的變化時對象被通知。它是基于NSKeyValueObserving 非正式協議。觀察到的屬性可以是簡單的屬性,一個一關系,或一對多的關系。在模型視圖控制器模式下,鍵值觀察尤為重要,因為它使視圖對象模型對象的觀察通過控制器層的變化。因此,這是Cocoa的一個必不可少的綁定技術的組成部分。

Cocoa提供了一個默認“自動”的實施NSKeyValueObserving方法:給所有符合對象的屬性的觀察能力。

使用和限制

KVO是類似的通知機制,但在一些重要的方面不同。在鍵值觀察沒有中央的對象,提供所有觀察員變更通知。相反,變化通知直接發送到觀察對象。鍵值觀察也直接關系到具體對象的屬性值。另一方面,通知機制,更廣泛的關注程序事件。

對象參與鍵值觀察(KVO)必須KVO兼容即遵守一定的要求。對于自動觀測,這需要符合要求的關鍵值編碼(KVC依從性)和使用KVC的依從性的方法(即,訪問器方法)。鍵值編碼是一種機制(基于相關的非正式協議)自動獲取和設置對象屬性的值。

你可以通過禁用自動化KVO通知觀察者通知,使用方法NSKeyValueObserving非正式的協議和相關的類執行手動通知。

代理(Proxy)

代理設計模式提供了一種替代,或占位符,為另一個對象來控制訪問其他對象。使用這個模式來創建一個代表或代理,對象,控制訪問另一個對象,這可能是遠程的,復雜的創建,或需要保護。這種模式的結構類似于裝飾模式卻有不同的用途;裝飾給對象添加行為,而代理控制對對象的訪問。

NSProxy

NSProxy類定義了對象作為其他對象的代理對象的接口,甚至對象還不存在。一個代理對象通常轉發消息給它代表的對象,但它也可以響應消息,通過加載對象轉變為它或代表。雖然NSProxy是一個抽象類,它實現了NSObject協議和其他基本方法的根對象的預期;事實上,一個層次結構的基類,如NSObject類

具體的NSProxy子類能夠完成既定目標的代理模式,如昂貴的對象或作為安全哨兵懶實例化對象。NSDistantObject,基礎框架中一個NSProxy具體子類,實現了一個遠程代理,對于透明的分布式消息。NSDistantObject對象是分布式對象結構的一部分。作為對其他進程或線程對象的代理,它們有助于使這些線程或進程的對象之間的通信。

NSInvocation 對象,這是命令模式的一種適應體,也是分布式對象體系結構的一部分

使用和限制

Cocoa只有在分布式對象采用NSProxy對象。這個NSProxy對象是具體的實例,是具體子類NSDistantObject和NSProtocolChecker。不僅可以使用分布式對象為進程消息(在相同的或不同的計算機)也可以用它來實現分布式計算和并行處理。如果你想使用代理對象的其他用途,如昂貴的資源或安全的創造,你要實現你自己的具體的NSProxy子類

接待員(Receptionist)

前臺設計模式是一種混合模式。雖然它沒有出現在“四人幫”的書,它結合了命令,備忘錄的元素,和本文中描述的代理設計模式。這也是蹦床模式(Trampoline pattern)的一個變種(其中還沒有出現在書中);在這種模式中,一個事件最初是由一個蹦床對象接收,這樣叫因為它立刻反彈,或重定向,處理到目標對象的事件。

當你需要反彈繼續處理另一個執行上下文,可以通過前臺設計模式。當你觀察一個通知,或者實現一個塊處理程序,或響應一個消息,你要確保你的代碼在適當的執行上下文中執行,可以實現前臺模式改變所必須做的工作,執行上下文。前臺模式,在反彈任務數據處理之前,甚至可以執行一些過濾或合并輸入數據。例如,可以收集數據分批進入,然后在區間調度這些批次做其他處理。

一種常見的情況,接待員模式是有用的鍵值觀察。對一個模型對象的屬性的值的變化是通過KVO通知傳達給觀察者。然而,一個模型對象的變化可以在后臺線程上發生。這個結果在一個線程不匹配,因為一個模型對象的狀態變化通常會導致更新用戶界面,這些都必須在主線程中發生。在這種情況下,你想重定向KVO通知主線程。

前臺設計模式的實踐

KVO通知調用由觀察者實現的observeValueForKeyPath:ofObject:change:context:方法。如果改變的屬性發生在輔助線程,該observeValueForKeyPath:ofObject:change:context:在同一個線程執行的代碼。在這個模式中有中央的對象,前臺接待員,作為一個線程的中介。下圖說明,接待對象被分配作為一個模型對象的屬性的觀察。前臺實現observeValueForKeyPath:ofObject:change:context:將收到的通知在輔助線程上的另一個執行上下文的主要操作隊列,在這種情況下。屬性變化時,接待員收到一個KVO通知。接待員立即增加一塊操作的主要操作隊列;塊包含指定的更新用戶界面的適當代碼。

定義一個接待員類具有元素需要添加本身作為一個觀察者的屬性,然后將一個KVO通知到一個更新的任務。因此,它必須知道它的觀察對象,該對象的屬性,這是觀察,什么更新任務執行,什么隊列執行它。下面代碼顯示初始聲明RCReceptionist類及其實例變量。

@interface RCReceptionist : NSObject {id observedObject;NSString *observedKeyPath;RCTaskBlock task;NSOperationQueue *queue; }

RCTaskBlock實例變量是下面這樣的block對象

typedef void (^RCTaskBlock)(NSString *keyPath, id object, NSDictionary *change);

observeValueForKeyPath:ofObject:change:context: 方法的參數是相似的,參數類聲明單例類工廠方法,rctaskblock對象是一個參數:

+ (id)receptionistForKeyPath:(NSString *)pathobject:(id)objqueue:(NSOperationQueue *)queuetask:(RCTaskBlock)task;

它實現了該方法分配傳入的值來實例化被接待員對象創建的實例變量,對象為模型對象屬性的一個觀察者

+ (id)receptionistForKeyPath:(NSString *)path object:(id)obj queue:(NSOperationQueue *)queue task:(RCTaskBlock)task {RCReceptionist *receptionist = [RCReceptionist new];receptionist->task = [task copy];receptionist->observedKeyPath = [path copy];receptionist->observedObject = [obj retain];receptionist->queue = [queue retain];[obj addObserver:receptionist forKeyPath:pathoptions:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:0];return [receptionist autorelease]; }

注意代碼復制的block對象而不是retaining它。因為bock可能是在棧上創建的,它必須被復制到堆,,KVO通知時它得存在于內存中。

最后,observeValueForKeyPath:ofObject:change:context:方法參數的實現:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)objectchange:(NSDictionary *)change context:(void *)context {[queue addOperationWithBlock:^{task(keyPath, object, change);}]; }

這個代碼在給定的運行隊列進行簡單的查詢任務,通過被觀察對象的task block,為改變屬性的關鍵路徑,和字典包含新value。任務是封裝在一個NSBlockOperation對象執行任務隊列。

客戶端對象提供的block代碼,更新用戶界面創建一個接待員對象時,如下面代碼,請注意,創建的接待對象時,客戶端傳給在運行隊列的數據block被執行,在這種情況下的主要操作隊列。

RCReceptionist *receptionist = [RCReceptionist receptionistForKeyPath:@"value" object:model queue:mainQueue task:^(NSString *keyPath, id object, NSDictionary *change) {NSView *viewForModel = [modelToViewMap objectForKey:model];NSColor *newColor = [change objectForKey:NSKeyValueChangeNewKey];[[[viewForModel subviews] objectAtIndex:0] setFillColor:newColor];}];

單例(Singleton)

單例設計模式確保一個類只有一個實例,并提供一個訪問它的全局訪問點。這類跟蹤它的唯一實例,可以確保沒有其他實例可以被創建。單例類是適當的情況下,對于提供一個全球性的資源是有意義的一個對象。

框架類

幾個Cocoa框架類是單例。他們包括NSFileManager,NSWorkspace,NSApplication以及在UIKit中,UIApplication。一個進程是限制這些類只有一個實例。當客戶端請求一個實例的類,它獲取一個共享實例,這是建立在第一次請求時懶創建的。

使用和限制

使用通過單例類返回的共享實例,和使用非單例類的一個實例沒什么不同,只是你無法copying、retaining或者releasing它(有關方法重新實現零操作)。如果情況需要可以創建你自己的單例類

模板方法

模板方法設計模式定義一個操作中的算法的骨架,而將一些步驟延遲到子類。模板方法模式讓子類重新定義算法中的某些步驟而不改變算法的結構。

重寫框架方法

模板方法模式是一個基本的Cocoa設計,而且面向對象框架是很普遍的。在Cocoa的模式讓一個程序把自己的自定義組件為一個算法,但框架組件決定何時需要它們。Cocoa類的編程接口通常包括由子類重寫方法。在運行時,框架調用這些所謂的通用方法在某些點的任務執行。一般的方法提供了一種用于自定義代碼提供程序特定的行為和數據的任務執行和協調的框架類結構。

使用和限制

利用Cocoa改編的模板方法模式,你必須創建一個類的子類并重寫這些方法,框架調用插入應用程序特定的輸入方法是執行。如果你寫自己的框架,你應該包括在設計模式。

總結

以上是生活随笔為你收集整理的Cocoa设计模式(iOS常用设计模式) Cocoa Design Patterns的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。