【设计模式】二、观察者模式
一、概述
观察者模式又叫做发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己。
一个软件系统常常要求在某一个对象的状态发生变化的时候,某些其它的对象做出相应的改变。做到这一点的设计方案有很多,但是为了使系统能够易于复用,应该选择低耦合度的设计方案。减少对象之间的耦合有利于系统的复用,但是同时设计师需要使这些低耦合度的对象之间能够维持行动的协调一致,保证高度的协作(Collaboration)。观察者模式是满足这一要求的各种设计方案中最重要的一种。
类比:它的关系类似于报纸的订阅。出版者(subject)+订阅者(observer)=观察者模式。
观察者模式提供一种对象设计,让主题和观察者之间松耦合。当两个对象之间松耦合,他们依然可以相互江湖,但是不太清楚彼此的细节。
改变主题或者观察者的一方,并不会影响另一方,因为两者是松耦合的,所以只要他们之间的接口仍被遵守,我们就可以自由的改变他们。
设计原则:为了交互对象之间的松耦合而努力。
二、在OC中的实现
1、KVO
Key-Value Observing,它提供一种机制,当指定的对象的属性被修改后,则对象就会接受到通知。每次指定的被观察的对象的属性被修改后,KVO自动通知相应的观察者。
model中定义:
@interface StockData : NSObject { NSString * stockName; float price; } @end @implementation StockData @end
controller中使用,记得上一篇怎么说的吗?这里相当于跟模型说,我要收听你的更新广播
- (void)viewDidLoad { [super viewDidLoad]; stockForKVO = [[StockData alloc] init]; [stockForKVO setValue:@"searph" forKey:@"stockName"]; [stockForKVO setValue:@"10.0" forKey:@"price"]; [stockForKVO addObserver:self forKeyPath:@"price" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:NULL]; myLabel = [[UILabel alloc]initWithFrame:CGRectMake(100, 100, 100, 30 )]; myLabel.textColor = [UIColor redColor]; myLabel.text = [stockForKVO valueForKey:@"price"]; [self.view addSubview:myLabel]; UIButton * b = [UIButton buttonWithType:UIButtonTypeRoundedRect]; b.frame = CGRectMake(0, 0, 100, 30); [b addTarget:self action:@selector(buttonAction) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:b]; }
用户单击View中的button调用控制器中的action去更改模型中的数据
-(void) buttonAction { [stockForKVO setValue:@"20.0" forKey:@"price"]; }
控制器需要实现的回调,相当于收到广播后我应该做啥事
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if([keyPath isEqualToString:@"price"]) { myLabel.text = [stockForKVO valueForKey:@"price"]; } }
视图dealloc需要取消观察
- (void)dealloc { [super dealloc]; [stockForKVO removeObserver:self forKeyPath:@"price"]; [stockForKVO release]; }
2、Notification
通知使用起来非常的简单:
首先定义回调,即发生通知了我应该做啥事。
- (void)callBack{ NSLog(@"我收到通知了!"); }
其次,注册通知,即告诉通知中心,我对啥通知感兴趣
[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(callBack) name: @"A类通知" object: nil];
第三,在程序任何一个地方都可以发送通知
- (void)getNotofocation{ NSLog(@"get it."); //发出通知 [[NSNotificationCenter defaultCenter] postNotificationName:@"A类通知" object:self]; }
当然,也可以在需要的时候取消注册通知。