iOS 常见的观察者模式主要有通知和 KVO 这两种,通知可以实现一对多的关系, KVO 可以观察属性值的变化.虽然小编开发中经常用到观察者模式这种设计模式,但总觉得理解不是很深入 .
通知模式
image.pngKVO 监听
image.png下边会用一个例子详细的阐述观察者这种设计模式具体使用场景
image.png这是一个酒店里经常可以看到的墙上挂的不同时区时间的钟表,我们以我国东八区北京时间为基准,当北京时间发生改变 ,其他几个城市时间也会相应的发生改变
首先定义一个 观察者对象的基类
/**
观察者对象
*/
@interface Observer : NSObject
{
@public
int _hour;
int _min;
int _sec;
}
/**
改变时 分 秒
*/
- (void)updateHour:(int)hour minute:(int)min seconds:(int)sec;
@end
///美国标准时间观察者
/**
美国标准时间
*/
@interface AmericaTimerObserver : Observer
@end
#import "AmericaTimerObserver.h"
@implementation AmericaTimerObserver
- (void)updateHour:(int)hour minute:(int)min seconds:(int)sec {
NSAssert((hour >= 0 && hour<=23),@"Hour 必须0~23之间");
NSAssert((min>=0&& min<=59),@"Min 必须0~59之间");
NSAssert((sec>=0&& sec<=59),@"Sec 必须0~59之间");
_hour = MIN(hour-13,24);
if (_hour < 0) {
_hour = 24 + _hour;
}
if (_hour == 24) {
_hour = 0;
}
_min = min;
_sec = sec;
[self dis];
}
/**
输出美国当前时间
*/
- (void) dis {
printf("\n************************\n");
printf("America Time is update\n");
printf("H: %d M: %d S:%d\n",_hour,_min,_sec);
}
@end
东京时间观察者对象
/**
日本标准时间
*/
@interface JapanTimerObserver : Observer
@end
#import "JapanTimerObserver.h"
@implementation JapanTimerObserver
- (void)updateHour:(int)hour minute:(int)min seconds:(int)sec {
NSAssert((hour >= 0 && hour<=23),@"Hour 必须0~23之间");
NSAssert((min>=0&& min<=59),@"Min 必须0~59之间");
NSAssert((sec>=0&& sec<=59),@"Sec 必须0~59之间");
_hour = MIN(hour+1,24);
if (_hour == 24) {
_hour = 0;
}
_min = min;
_sec = sec;
[self dis];
}
/**
输出美国当前时间
*/
- (void) dis {
printf("\n************************\n");
printf("Jppan Time is update\n");
printf("H: %d M: %d S:%d\n",_hour,_min,_sec);
}
@end
然后创建一个订阅者基类对象 只声明接口 并不负责具体实现
#import <Foundation/Foundation.h>
@class Observer;
@interface Subject : NSObject
{
@public
NSMutableArray <Observer *> *_observerList;
}
/**
注册通知
*/
- (void) registerObserver:(Observer *)ob;
/**
移除通知
*/
- (void) removeObserver:(Observer *)ob;
/**
通知所有监听通知的对象
*/
- (void) notify;
@end
子类 北京时间订阅者对象
/**
标准的北京时间
*/
@interface PekingTimeSubject : Subject
{
@private
int _hour;
int _min;
int _sec;
}
- (void) setTimerHour:(int)hour minute:(int)min seconds:(int)sec;
@end
#import "Observer.h"
#import "PekingTimeSubject.h"
@implementation PekingTimeSubject
- (instancetype)init
{
self = [super init];
if (self) {
_observerList = [NSMutableArray array];
}
return self;
}
- (void)setTimerHour:(int)hour minute:(int)min seconds:(int)sec {
NSAssert((hour >= 0 && hour<=23),@"Hour 必须0~23之间");
NSAssert((min>=0&& min<=59),@"Min 必须0~59之间");
NSAssert((sec>=0&& sec<=59),@"Sec 必须0~59之间");
_hour = hour;
_min = min;
_sec = sec;
[self dis];
[self notify];
}
- (void) dis {
printf("\n************************\n");
printf("Beijing Time is update\n");
printf("H: %d M: %d S:%d\n",_hour,_min,_sec);
}
- (void)notify {
for (Observer *observer in _observerList) {
[observer updateHour:_hour minute:_min seconds:_sec];
}
}
- (void)registerObserver:(Observer *)ob {
[_observerList addObject:ob];
}
- (void)removeObserver:(Observer *)ob {
[_observerList removeObject:ob];
}
@end
具体使用示例代码
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"Hello, World!");
PekingTimeSubject *bjTime = [[PekingTimeSubject alloc] init];
JapanTimerObserver *jp = [[JapanTimerObserver alloc] init];
AmericaTimerObserver *am = [[AmericaTimerObserver alloc] init];
[bjTime registerObserver:jp];
[bjTime registerObserver:am];
[bjTime setTimerHour:10 minute:0 seconds:0];
[bjTime removeObserver:jp];
[bjTime setTimerHour:12 minute:0 seconds:0];
}
return 0;
}
image.png
当注册一个观察者对象后 如果北京时间改变了 那么订阅了这个通知的对象 也会跟着改变
网友评论