iOS應(yīng)用開發(fā)中使用設(shè)計(jì)模式中的觀察者模式的實(shí)例
在軟件開發(fā)中,無論是那種高級(jí)語言中總會(huì)伴隨著一些最為常用的設(shè)計(jì)模式,即便就如iOS開發(fā)中與我們打交道最多的無非就是單例模式、觀察者模式和工廠模式了,當(dāng)然了其他的設(shè)置模式也同樣存在在編程的很多地方。下面就就讓我們簡單的了解下觀察者模式吧!
觀察者模式本質(zhì)上時(shí)一種發(fā)布-訂閱模型,用以消除具有不同行為的對(duì)象之間的耦合,通過這一模式,不同對(duì)象可以協(xié)同工作,同時(shí)它們也可以被復(fù)用于其他地方Observer從Subject訂閱通知,ConcreteObserver實(shí)現(xiàn)重現(xiàn)ObServer并將其重載其update方法。一旦SubJect的實(shí)例需要通知Observer任何新的變更,Subject會(huì)發(fā)送update消息來通知存儲(chǔ)在其內(nèi)部類中所注冊(cè)的Observer、在ConcreteObserver的update方法的實(shí)際實(shí)現(xiàn)中,Subject的內(nèi)部狀態(tài)可被取得并進(jìn)行后續(xù)處理。其類圖如下:
由上面我們可以發(fā)現(xiàn)觀察者模式無非在是定義對(duì)象間的一種一對(duì)多的依賴關(guān)系,并且當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變的時(shí)候,所有依賴于它的對(duì)象都會(huì)得到通知且自動(dòng)更新。即如果Subject允許其他觀察者(實(shí)現(xiàn)了觀察者接口的對(duì)象)對(duì)這個(gè)Subject的改變進(jìn)行請(qǐng)閱,當(dāng)Subject發(fā)送了變化,那么Subject會(huì)將這個(gè)變化發(fā)送給所有的觀察者,觀察者就能對(duì)Subject的變化做出更新。其時(shí)序圖如下
通過上面的觀察我們可以發(fā)現(xiàn)如果用N個(gè)Observer來拓展Subject的行為,這些Observer具有處理存儲(chǔ)在Subject中的信息的特定實(shí)現(xiàn),這樣也就實(shí)現(xiàn)了前面所說的消除不同對(duì)象間的耦合的功能了。
那么了解了這些我們可能就會(huì)更像了解下我們?cè)谑裁磿r(shí)候才會(huì)去使用觀察者模式呢?
當(dāng)需要將改變通知所有的對(duì)象時(shí),而你又不知道這些對(duì)象的具體類型
改變發(fā)生在同一個(gè)對(duì)象中,并需要改變其他對(duì)象將相關(guān)的狀態(tài)進(jìn)行更新且不知道有多少個(gè)對(duì)象。
而同樣的在我們?nèi)粘5拈_發(fā)中在Cocoa Touch框架中的的兩種經(jīng)常打交道的技術(shù)KVO與通知都實(shí)現(xiàn)了觀察者模式,所以下面我們討論的重點(diǎn)也就是基于這兩個(gè)方面的。
通知
言歸正傳,在Cocoa Touch框架中NSNotificationCenter和NSNotification對(duì)象實(shí)現(xiàn)了一對(duì)多的模型。通過NSNotificationCenter可以讓對(duì)象之間進(jìn)行通訊,即便這些對(duì)象之間并不認(rèn)識(shí)。下面我們來看下NSNotificationCenter發(fā)布消息的方法:
NSNotification * subjectMessage = [ NSNotification notificationWithName:@"subjectMessage" object: self];
NSNotificationCenter * notificationCenter = [ NSNotificationCenter defaultCenter];
[notificationCenter postNotification:subjectMessage];
通過上面的代碼我們創(chuàng)建了一個(gè)名為subjectMessage的NSNotification對(duì)象,然后通過notificationCenter來發(fā)布這個(gè)消息。通過向NSNotificationCenter類發(fā)送defaulCenter消息,可以得到NSNotificationCenter實(shí)例的引用。每個(gè)進(jìn)程中只有一個(gè)默認(rèn)的通知中心,所以默認(rèn)的NSNotificationCenter是個(gè)單例對(duì)象。如果有其他觀察者定于了其對(duì)象的相關(guān)事件則可以通過以下的方法來進(jìn)行操作:
NSNotificationCenter * notificationCenter1 = [ NSNotificationCenter defaultCenter];
[notificationCenter addObserver: self selector: @selector(update:) name:@"subjectMessage" object: nil ];
經(jīng)過以上步驟我們已經(jīng)向通知中心注冊(cè)了一個(gè)事件并且通過selector制定了一個(gè)方法update:下面我們可以實(shí)現(xiàn)以下這個(gè)方法
- (void)update:(NSNotification*)notification{
if ([[notification name] isEqualToString:@"subjectMessage"]) {
NSLog(@"%@",@"猴子派來的救兵去哪了?");
}
}
當(dāng)然最后如果我們需要對(duì)監(jiān)聽進(jìn)行銷毀
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
實(shí)例
抽象主題協(xié)議:
#import <Foundation/Foundation.h>
@class Observer;
/*!
* 抽象主題協(xié)議
*
* @since V1.0
*/
@protocol Subject <NSObject>
@required
/*!
* 增加觀察者
*
* @param observer 觀察者實(shí)例
*
* @since V1.0
*/
-(void)attach:(Observer*) observer;
/*!
* 移除觀察者
*
* @param observer 觀察者實(shí)例
*
* @since V1.0
*/
-(void)detach:(Observer*) observer;
/*!
* 為觀察者發(fā)送通知
*
* @since V1.0
*/
-(void)notifyObservers;
@end
觀察者協(xié)議:
#import <Foundation/Foundation.h>
/*!
* 觀察者協(xié)議
*
* @since V1.0
*/
@protocol Observer <NSObject>
@required
-(void)update;
@end
具體的觀察者類:
#import <Foundation/Foundation.h>
#import "Observer.h"
/*!
* 具體的觀察者類
*
* @since V1.0
*/
@interface ConcreteObserver : NSObject<Observer>
@end
具體主題類:
#import <Foundation/Foundation.h>
#import "Subject.h"
/*!
* 具體主題類
*
* @since V1.0
*/
@interface ConcreteSubject : NSObject<Subject>
{
NSMutableArray *observers;
}
@property(nonatomic,strong)NSMutableArray* observers;
/*!
* 單例構(gòu)建自身對(duì)象
*
* @return 自身對(duì)象
*
* @since V1.0
*/
+(ConcreteSubject*)shareConcreteSubject;
@end
了解過通知之后我們來看一下KVO
KVO是Cocoa提供的一種稱為鍵值觀察的機(jī)制,對(duì)象可以通過它得到其他對(duì)象特定屬性的變更通知。而這個(gè)機(jī)制是基于NSKeyValueObserving非正式些,Cocoa通過這個(gè)協(xié)議為所有遵循協(xié)議的對(duì)象提供了一種自動(dòng)化的屬性監(jiān)聽的功能。
雖然通知和KVO都可以對(duì)觀察者進(jìn)行實(shí)現(xiàn),但是他們之間還是略有不同的,由上面的例子我們可以看出通知是由一個(gè)中心對(duì)象為所有觀察者提供變更通知,主要是廣義上關(guān)注程序事件,而KVO則是被觀察的對(duì)象直接想觀察者發(fā)送通知,主要是綁定于特定對(duì)象屬性的值。下面我們通過一個(gè)簡單的例子來了解下他的一些是使用方法
首先我們有Hero這個(gè)模型
@property (nonatomic,copy) NSString * name;@property (nonatomic,copy) NSString * title;@property (nonatomic,assign) NSUInteger age;
在控制其中我們將其初始化并賦值
self.hero = [[Hero alloc] init];
self.hero.name = @"趙云";
self.hero.title = @"將軍";
self.hero.age = 87;
現(xiàn)在我們的這個(gè)對(duì)象基本有值了,那么我們將這個(gè)對(duì)象的name監(jiān)聽下他的改變
[self.hero addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
觸發(fā)通知并將值改變
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
self.hero.name = @"張飛";
}
在制定的回調(diào)函數(shù)中,處理收到的更改通知
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
if([keyPath isEqualToString:@"name"])
{
NSLog(@"賦值后--%@",self.hero.name);
NSLog(@"新的值--%@",change[@"new"]);
NSLog(@"以前的值--%@",change[@"old"]);
}
}
回調(diào)打印如下:
最后注銷觀察者
- (void)dealloc{
[self.hero removeObserver:self forKeyPath:@"name"];
}
到了這里觀察者模式中常用的KVO及通知的內(nèi)容就到這里,不過要知道這里談及的只是最基礎(chǔ)的用法,后面我們可能還是有更加深入的探究,或者在后續(xù)中可能還會(huì)對(duì)比iOS中的代理以及Block來探尋下iOS中的消息傳遞機(jī)制,再或者像Swift中的didSet、willSet的屬性監(jiān)聽的方法,這些都是很好玩的內(nèi)容,不是么?
- 舉例講解iOS應(yīng)用開發(fā)中對(duì)設(shè)計(jì)模式中的策略模式的使用
- iOS App使用設(shè)計(jì)模式中的模板方法模式開發(fā)的示例
- iOS應(yīng)用設(shè)計(jì)模式開發(fā)中對(duì)簡單工廠和工廠方法模式的運(yùn)用
- 實(shí)例講解設(shè)計(jì)模式中的命令模式在iOS App開發(fā)中的運(yùn)用
- iOS App設(shè)計(jì)模式開發(fā)之適配器模式使用的實(shí)戰(zhàn)演練
- 設(shè)計(jì)模式中的Memento備忘錄模式的在iOS App開發(fā)中的運(yùn)用
- 實(shí)例講解iOS應(yīng)用的設(shè)計(jì)模式開發(fā)中的Visitor訪問者模式
- 實(shí)例講解如何在iOS應(yīng)用開發(fā)中使用設(shè)計(jì)模式中的代理模式
- iOS App設(shè)計(jì)模式開發(fā)中策略模式的實(shí)現(xiàn)示例
相關(guān)文章
iOS實(shí)現(xiàn)自定義起始時(shí)間選擇器視圖
本篇文章主要介紹了iOS實(shí)現(xiàn)自定義起始時(shí)間選擇器視圖,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-06-06iOS程序開發(fā)之使用PlaceholderImageView實(shí)現(xiàn)優(yōu)雅的圖片加載效果
這篇文章主要介紹了ioS程序開發(fā)之使用PlaceholderImageView實(shí)現(xiàn)優(yōu)雅的圖片加載效果的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-09-09iOS應(yīng)用腳本重簽名的實(shí)現(xiàn)方法
這篇文章主要介紹了iOS應(yīng)用腳本重簽名的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-01-01詳解iOS應(yīng)用的設(shè)計(jì)模式開發(fā)中Mediator中介者模式的使用
這篇文章主要介紹了iOS應(yīng)用的設(shè)計(jì)模式開發(fā)中Mediator中介者模式的使用,示例代碼為傳統(tǒng)的Objective-C語言,需要的朋友可以參考下2016-03-03