欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

iOS應(yīng)用開發(fā)中使用設(shè)計(jì)模式中的觀察者模式的實(shí)例

 更新時(shí)間:2016年03月17日 09:52:37   作者:曉風(fēng)沐晨  
這篇文章主要介紹了iOS應(yīng)用開發(fā)中使用設(shè)計(jì)模式中的觀察者模式的實(shí)例,包括Cocoa框架使用中的KVO機(jī)制的相關(guān)配合運(yùn)用,代碼為傳統(tǒng)的Objective-C,需要的朋友可以參考下

在軟件開發(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ù)處理。其類圖如下:

201631795044843.jpg (737×317)


由上面我們可以發(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í)序圖如下

201631795111827.png (466×255)

通過上面的觀察我們可以發(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ā)布消息的方法:

復(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)行操作:
復(fù)制代碼 代碼如下:

    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è)方法
復(fù)制代碼 代碼如下:

- (void)update:(NSNotification*)notification{

        if ([[notification name] isEqualToString:@"subjectMessage"]) {
            NSLog(@"%@",@"猴子派來的救兵去哪了?");

        }
}


當(dāng)然最后如果我們需要對(duì)監(jiān)聽進(jìn)行銷毀
復(fù)制代碼 代碼如下:

- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

實(shí)例
抽象主題協(xié)議:

復(fù)制代碼 代碼如下:

#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é)議:
復(fù)制代碼 代碼如下:

#import <Foundation/Foundation.h> 
 
/*!
 *  觀察者協(xié)議
 *
 *  @since V1.0
 */ 
@protocol Observer <NSObject> 
 
@required 
-(void)update; 
 
@end 

具體的觀察者類:
復(fù)制代碼 代碼如下:

#import <Foundation/Foundation.h> 
#import "Observer.h" 
 
/*!
 *  具體的觀察者類
 *
 *  @since V1.0
 */ 
 
@interface ConcreteObserver : NSObject<Observer> 
 
@end 

具體主題類:
復(fù)制代碼 代碼如下:

#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è)模型

復(fù)制代碼 代碼如下:

@property (nonatomic,copy) NSString * name;@property (nonatomic,copy) NSString * title;@property (nonatomic,assign) NSUInteger age;

在控制其中我們將其初始化并賦值
復(fù)制代碼 代碼如下:

    self.hero = [[Hero alloc] init];
    self.hero.name = @"趙云";
    self.hero.title = @"將軍";
    self.hero.age = 87;

現(xiàn)在我們的這個(gè)對(duì)象基本有值了,那么我們將這個(gè)對(duì)象的name監(jiān)聽下他的改變
復(fù)制代碼 代碼如下:

[self.hero addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];

觸發(fā)通知并將值改變
復(fù)制代碼 代碼如下:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    self.hero.name = @"張飛";
}

在制定的回調(diào)函數(shù)中,處理收到的更改通知
復(fù)制代碼 代碼如下:

- (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)打印如下:

201631795149534.png (211×54)


最后注銷觀察者

復(fù)制代碼 代碼如下:

- (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)容,不是么?

相關(guān)文章

最新評(píng)論