当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。
观察者模式UML从UML图可以看到,观察者模式有两大类:主题和观察者,有以下四个角色:
(1)Subject:抽象主题,他把所有观察者对象保存在一个集合里,可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象。
(2)ConcreteSubject:具体主题,该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知
(3)Observer:抽象观察者,是观察者者的抽象类,它定义了一个更新接口,使得在得到主题更改通知时更新自己。
(4)ConcrereObserver:具体观察者,实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。
举例说明
案例:订阅书刊。
1.定义接口
@protocol SubjectProtocol <NSObject>
- (NSString*)test;
- (void)subMessage:(id)message withSubNumber:(NSString *)withSubNumber;
@end
2.主题
@interface SubjectCenter : NSObject
// 创建书刊订阅号
+ (void)creatNumber:(NSString *)subNumber;
// 移除订阅号
+ (void)removeNumber:(NSString *)subNumber;
// 添加用户
+ (void)addUser:(id <SubjectProtocol>)user wihtNumber:(NSString *)userNumber;
// 移除用户
+ (void)removeUser:(id <SubjectProtocol>)user withNumber:(NSString *)userNumber;
// 发送消息
+ (void)sendMessage:(id)message withSubNumber:(NSString *)SubNumber;
实现中,使用NSHashTable来保存使用者,NSHashTable 就是一个集合,但是它是弱引用的。
#import "SubjectCenter.h"
static NSMutableDictionary *bookCenter = nil;
@implementation SubjectCenter
+ (void)initialize {
if (self == [SubjectCenter class]) {
bookCenter = [NSMutableDictionary dictionary];
}
}
// 创建书刊订阅号
+ (void)creatNumber:(NSString *)subNumber {
NSHashTable *hashTable = [self existNumber:subNumber];
if (hashTable == nil) {
hashTable = [NSHashTable weakObjectsHashTable];
[bookCenter setObject:hashTable forKey:subNumber];
}
}
// 移除订阅号
+ (void)removeNumber:(NSString *)subNumber {
NSHashTable *hashTable = [self existNumber:subNumber];
if (hashTable) {
[bookCenter removeObjectForKey:subNumber];
}
}
// 添加用户
+ (void)addUser:(id <SubjectProtocol>)user wihtNumber:(NSString *)userNumber {
NSHashTable *hashTable = [self existNumber:userNumber];
[hashTable addObject:user];
}
// 移除用户
+ (void)removeUser:(id <SubjectProtocol>)user withNumber:(NSString *)userNumber {
NSHashTable *hashTable = [self existNumber:userNumber];
[hashTable removeObject:user];
}
// 发送消息
+ (void)sendMessage:(id)message withSubNumber:(NSString *)SubNumber {
NSHashTable *hashTable = [self existNumber:SubNumber];
if (hashTable) {
NSEnumerator *enumerato = [hashTable objectEnumerator];
id <SubjectProtocol> object = nil;
while (object = [enumerato nextObject]) {
if ([object respondsToSelector:@selector(subMessage:withSubNumber:)]) {
[object subMessage:message withSubNumber:SubNumber];
}
}
}
}
// 实现了代理方法
+ (NSHashTable *)existNumber:(NSString *)subStringNumber {
return [bookCenter objectForKey:subStringNumber];
}
@end
3.观察者观察
@interface ViewController () <SubjectProtocol>
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// 创建订阅
[SubjectCenter creatNumber:@"string"];
// 添加订阅
[SubjectCenter addUser:self wihtNumber:@"string"];
// 发送消息
[SubjectCenter sendMessage:@"11" withSubNumber:@"string"];
}
- (void)subMessage:(id)message withSubNumber:(NSString *)withSubNumber {
NSLog(@"----%@----%@",message, withSubNumber);
}
@end
load和initialize方法详见这篇文章
KVO就是一种观察者模式的设计
KVO的底层实现原理请看这篇文章
网友评论