IOS設計模式-觀察者模式

来源:http://www.cnblogs.com/goodboy-heyang/archive/2016/03/11/5265675.html
-Advertisement-
Play Games

前言:23種軟體設計模式中的觀察者模式,也是在軟體開發中,挺常用的一種設計模式。而在蘋果開發中,蘋果Cocoa框架已經給我們實現了這個設 計模式,那就是通知和KVO(Key-Value Observing),本篇博文將會先講解通知和KVO的常用方法和使用示例,然後講解觀察者模式以及對觀察者模式的實現


 前言:23種軟體設計模式中的觀察者模式,也是在軟體開發中,挺常用的一種設計模式。而在蘋果開發中,蘋果Cocoa框架已經給我們實現了這個設 計模式,那就是通知和KVO(Key-Value Observing),本篇博文將會先講解通知和KVO的常用方法和使用示例,然後講解觀察者模式以及對觀察者模式的實現。

 

文章內容大綱:

1、KVO的使用

2、通知的使用

3、觀察者模式

 

正文:

1、KVO的使用

addObserver:forKeyPath:options:context:

通知其他對象的方法,這個方法在NSObject中就已經申明瞭,也就是說任何繼承自NSObject的對象都可以使用KVO.

我們來實現一個對象a值改變的時候去通知對象b,也就是說這裡b就是a的觀察者,b觀察a的變化,然後做出相應的反應.

Model_A.h和Model_A.m:

  

  Model_B.h和Model_B.m:

  

  最後在ViewController.h中:

  

  輸出結果:

  2016-03-10 18:02:39.955 KVO[24772:539854] 程式開始執行!
  2016-03-10 18:02:41.959 KVO[24772:539854] Model_B

   -----------------------------------------------------------------------------------------------------------------------------------------------------------

  如果註釋掉Model_B中的方法observeValueForKeyPath:ofObject:change:context:,運行時會導致崩潰:

  

   也就是這麼一層關係:

  A對象要通知B對象,B對象必須實現監聽的方法,否則一旦有消息發送就會導致崩潰.

  A對象不想通知B對象了,需要從B對象身上移除掉通知.

 

  要想程式不出現問題,我們需要實現3步.

  (主動添加B的通知) A -------> B(不實現一個方法就崩潰)

  (主動移除B的通知) A ---X-->  B

(重覆移除B的通知) A ---X-->  B(崩潰)

  用起來很惡性,還好,我們可以重覆添加B的通知而不崩潰......

    但是要註意:添加的觀察者的次數要和移除觀察者的次數相等,少移除一個或者多移除一個都會造成程式崩潰:

   

  

 

2、 通知的使用

  Model.h和Model.m

  

  簡易封裝的通知中心類:Notification.h 和 Notification.m

  

  在ViewController.m中:

    

  輸出結果:

  2016-03-10 20:36:20.077 通知[28333:641372]
  Hello,NSConcreteNotification 0x7fbafbd0b620 {name = A; userInfo = Hello,a}!
  2016-03-10 20:36:20.078 通知[28333:641372]
  Hello,NSConcreteNotification 0x7fbafbd0bca0 {name = B; userInfo = Hello,b}!

 

3、觀察者模式

  關於觀察者模式,我們百度百科一下,會找到:

  觀察者模式(有時又被稱為發佈(publish )-訂閱(Subscribe)模式、模型-視圖(View)模式、源-收聽者(Listener)模式或從屬者模式)是軟體設計模式的一種。在此種模式中,一個目標物件管理所有相依於它的觀察者物件,並且在它本身的狀態改變時主動發出通知。這通常透過呼叫各觀察者所提供的方法來實現。此種模式通常被用來實現事件處理系統。

        

   在這個圖示例中,"訂閱書刊的用戶"需要向"書刊發行機構"提供基本的註冊信息,這些信息包括用戶自己的基本信息和要"訂閱的書刊號",然後確定成為" 書刊發行機構"的用戶,然後當"書刊發行機構"開始發行書刊,就會根據"訂閱書刊的用戶"的已經提供過的基本信息,進行發行書刊。然後"訂閱書刊的用戶" 就會得到相應的書刊。

  在這個"發行-訂閱"的模式中,"書刊發行機構"和"訂閱書刊的用戶"之間是靠"訂閱書刊的用戶"提供的基本有效的信息建立聯繫的。

  這個"發行-訂閱"的模式也是一種觀察者模式的一個生活中非常生動的例子。"書刊發行機構"相當於觀察者模式中的一個"通知中心"的角色,會根據實際需求根據用戶信息向用戶發送消息,然後用戶作為觀察者收到這些消息之後,就會自動的根據消息來執行自己的業務邏輯。

  接下來,我們要實現通知中心的抽象設計

  根據需求分析,首先我們需要一個唯一的"書刊發行機構",然後可以增加和刪除書刊,同時能存儲多個書刊,然後每個書刊又可以對應多個"訂閱書刊的用戶",

   另外要補充一個就是,在添加和移除用戶的介面中,我們需要傳入用戶信息對象,這個用戶信息對象我們需要用協議來約束它,我們思考一下,比如訂閱書刊,我 們當然需要用戶最基本的兩個信息,用戶的ID和用戶訂閱的書刊號,用戶的ID用於"書刊發行機構"能夠準確的發消息或者發書刊正確無誤的發對了人,這個作 用就好比我們唯一的身份證號碼的作用是一樣的。然後用戶訂閱的書刊號,就能保證"書刊發行機構"能把正確的書刊發到用戶手中,不能隨便什麼書刊都發向隨便 什麼人的吧。

  所以先寫出下麵所有的公開的介面,後面再具體實現它們,這就是面向介面設計:

    

  另外,當"書刊發行機構"有了新的書刊的時候,根據需求,創建一個書刊號,然後如果有新的用戶需要訂閱新的書刊,根據需求,創建一個用戶訂閱書刊的信息對象。

  一個書刊對應每個月會在某一天發佈新書,當"書刊發行機構"的現有的書刊有了新的書發佈的時候,就會發消息通知訂閱這個書刊的用戶,然後用戶會做出及時的響應回饋。

  按照觀察者模式,被觀察者發送消息,觀察者收到消息就需要立馬做出響應。這個和我們之前用的Cocoa框架已經實現的KVO和通知的模式是一樣的。

  為了實現這樣的模式,我們還需要給用戶信息對象用一個協議來約束它:

  

  接著我們為上面的公開的介面具體實現,但是我們需要選擇一個數據結構來存儲書刊號和訂閱書刊的用戶信息對象,這裡我選擇使用NSMutableDictionary的Key-Value來存儲書刊號和書刊,用NSHashTable來存儲用戶信息對象。

  那麼為什麼要用NSHashTable來存儲用戶信息呢?為什麼不用別的數據結構,比如數組(NSMutableArray)或者字典(NSMutableDictionary).

    因為NSHashTable會對添加進的對象持有弱引用,當添加進來的元素,外部對他持有的強引用都取消的時候,這個對象就會自動從記憶體中消除,這樣就不需要手動移除這些對象。

    這個相比Cocoa給我們實現的KVO和通知,就不需要我們手動去操作實現removeObserve方法了。

    雖然說,在使用NSHashTable實現的觀察者模式,觀察者對象本身就至少需要一個強引用,但是在實際開發中,觀察者往往都至少會有一個強引用的。

    所以,使用NSHashTable對系統算是一個小小的優化。

  

  然後接著我們使用前面創造的觀察者模式:

  CustomerA.h和CustomerA.m:

  

  在ViewController中,同時也把ViewController作為用戶對象,以self傳入:

  

  列印:

  2016-03-11 14:50:38.980 ObserverPattern[7958:175895] hashTable:NSHashTable {
  [5] <ViewController: 0x7f93d2d26ac0>
  [12] <CustomerA: 0x7f93d2c17f40>
  }
  2016-03-11 14:50:38.981 ObserverPattern[7958:175895] V1.0  SCIENCE
  2016-03-11 14:50:38.981 ObserverPattern[7958:175895]
  Hello,My Name is : CustomerA
    V1.0--SCIENCE

 備份的源碼鏈接: http://pan.baidu.com/s/1eQTnm50 密碼: s7su

 

 

 

 4、自己實現KVO(以後有時間補上)

 

轉載註明出處:http://www.cnblogs.com/goodboy-heyang/p/5265675.html ,尊重勞動成果。

 

本人最大的學習來源是閱讀一直走在行業里很前面的大牛寫的博客,有的博客還可能是一個團隊寫的,本人本篇深入學習的知識都是來自閱讀它們的文章,中國有傳統美德叫飲水思源,所以在這裡也分享分享與本篇知識相關的學習資料來源(附有超鏈接,點擊就能跳轉):

1、《KVO的使用

2、《通知中心NSNotificationCenter的使用

3、《3種方式實現KVO併進行對比

4、《手動設定實例變數的KVO實現監聽

5、《如何自己手動寫一個KVO

6、《需要羅列出所有的KVO的使用方法

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 用於Android開發的免費類庫和工具集合,按目錄分類。 Action Bars ActionBarSherlock Extended ActionBar FadingActionBar GlassActionBar v7 appcompat library 廣告 AdMob Google Mobi
  • android中的文件(圖片)上傳其實沒什麼複雜的,主要是對 multipart/form data 協議要有所瞭解。 關於 multipart/form data 協議,在 RFC文檔中有詳細的描述 [RFC 2388 Returning Values from Forms: multipart/
  • /** * 判斷當前時間是否處於某個時間段內 * * @param startTime 開始時間 * @param expireTime 結束時間 */ - (BOOL)validateWithStartTime:(NSString *)startTime withExpireTime:(NSStr
  • 本文從源碼角度剖析 RNA 中 Java <> Js 的通信機制(基於最新的 RNA Release 20)。 對於傳統 Java<>Js 通信而言,Js 調用 Java 通不外乎 Jsbridge、onprompt、log 及 addjavascriptinterface 四種方式,在 Java...
  • ReactNative官方中文文檔0.21,ReactNative官方中文文檔0.21.chm
  • interactivePopGestureRecognizer是iOS7推出的解決VeiwController滑動後退的新功能,雖然很實用,但是坑也很多啊,用過的同學肯定知道問題在哪裡,所以具體問題我就不描述了,這裡只給出如何完美解決interactivePopGestureRecognizer卡住
  • 這篇是關於網路請求的,結合公司的實際情況編寫,如果有不同意見歡迎留言共同討論。 iOS在9.0之後徹底放棄了NSURLConnection,現在已經改用了NSURLSession進行網路請求。一般現在網路請求也都是使用AFNetworking。下麵就把我自己關於afn和系統的api使用寫下來。 一.
  • 經測試發現,如果EditText預先有內容,游標自然會在文字的末尾 。 但是如果預先內容為空,然後設置好內容,這種情況下游標自然會在文字的開頭,所以這種情況下可以這樣做讓游標位於末尾:editText.setText("0");editText.requestFocus(); //這是關鍵
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...