在软件开发中,无论是那种高级语言中总会伴随着一些最为常用的设计模式,即便就如iOS开发中与我们打交道最多的无非就是单例模式、观察者模式和工厂模式了,当然了其他的设置模式也同样存在在编程的很多地方。下面就就让我们简单的了解下观察者模式吧!
观察者模式本质上时一种发布-订阅模型,用以消除具有不同行为的对象之间的耦合,通过这一模式,不同对象可以协同工作,同时它们也可以被复用于其他地方Observer从Subject订阅通知,ConcreteObserver实现重现ObServer并将其重载其update方法。一旦SubJect的实例需要通知Observer任何新的变更,Subject会发送update消息来通知存储在其内部类中所注册的Observer、在ConcreteObserver的update方法的实际实现中,Subject的内部状态可被取得并进行后续处理。其类图如下:
由上面我们可以发现观察者模式无非在是定义对象间的一种一对多的依赖关系,并且当一个对象的状态发生改变的时候,所有依赖于它的对象都会得到通知且自动更新。即如果Subject允许其他观察者(实现了观察者接口的对象)对这个Subject的改变进行请阅,当Subject发送了变化,那么Subject会将这个变化发送给所有的观察者,观察者就能对Subject的变化做出更新。其时序图如下
通过上面的观察我们可以发现如果用N个Observer来拓展Subject的行为,这些Observer具有处理存储在Subject中的信息的特定实现,这样也就实现了前面所说的消除不同对象间的耦合的功能了。
那么了解了这些我们可能就会更像了解下我们在什么时候才会去使用观察者模式呢?
当需要将改变通知所有的对象时,而你又不知道这些对象的具体类型
改变发生在同一个对象中,并需要改变其他对象将相关的状态进行更新且不知道有多少个对象。
而同样的在我们日常的开发中在Cocoa Touch框架中的的两种经常打交道的技术KVO与通知都实现了观察者模式,所以下面我们讨论的重点也就是基于这两个方面的。
通知
言归正传,在Cocoa Touch框架中NSNotificationCenter和NSNotification对象实现了一对多的模型。通过NSNotificationCenter可以让对象之间进行通讯,即便这些对象之间并不认识。下面我们来看下NSNotificationCenter发布消息的方法:
NSNotification * subjectMessage = [ NSNotification notificationWithName:@"subjectMessage" object: self]; NSNotificationCenter * notificationCenter = [ NSNotificationCenter defaultCenter]; [notificationCenter postNotification:subjectMessage];
NSNotificationCenter * notificationCenter1 = [ NSNotificationCenter defaultCenter]; [notificationCenter addObserver: self selector: @selector(update:) name:@"subjectMessage" object: nil ];
- (void)update:(NSNotification*)notification{if ([[notification name] isEqualToString:@"subjectMessage"]) { NSLog(@"%@",@"猴子派来的救兵去哪了?");
} }
- (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; }
实例
抽象主题协议:
#import <Foundation/Foundation.h> @class Observer; /*! * 抽象主题协议 * * @since V1.0 */ @protocol Subject <NSObject> @required /*! * 增加观察者 * * @param observer 观察者实例 * * @since V1.0 */ -(void)attach:(Observer*) observer; /*! * 移除观察者 * * @param observer 观察者实例 * * @since V1.0 */ -(void)detach:(Observer*) observer; /*! * 为观察者发送通知 * * @since V1.0 */ -(void)notifyObservers; @end
#import <Foundation/Foundation.h> /*! * 观察者协议 * * @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; /*! * 单例构建自身对象 * * @return 自身对象 * * @since V1.0 */ +(ConcreteSubject*)shareConcreteSubject; @end
了解过通知之后我们来看一下KVO
KVO是Cocoa提供的一种称为键值观察的机制,对象可以通过它得到其他对象特定属性的变更通知。而这个机制是基于NSKeyValueObserving非正式些,Cocoa通过这个协议为所有遵循协议的对象提供了一种自动化的属性监听的功能。
虽然通知和KVO都可以对观察者进行实现,但是他们之间还是略有不同的,由上面的例子我们可以看出通知是由一个中心对象为所有观察者提供变更通知,主要是广义上关注程序事件,而KVO则是被观察的对象直接想观察者发送通知,主要是绑定于特定对象属性的值。下面我们通过一个简单的例子来了解下他的一些是使用方法
首先我们有Hero这个模型
@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;
[self.hero addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ self.hero.name = @"张飞"; }
- (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"]);} }
最后注销观察者
- (void)dealloc{ [self.hero removeObserver:self forKeyPath:@"name"]; }
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:notice#nhooo.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。