观察者模式:具体的定义这里暂且不说了,书上有,只说说我个人的理解。
理解一:观察者模式角色分析:
书上有角色分析如下:
● 抽象主题(Subject)角色:抽象主题角色把所有对观察者对象的引用保存在一个聚集(比如ArrayList对象)里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象,抽象主题角色又叫做抽象被观察者(Observable)角色。
● 具体主题(ConcreteSubject)角色:将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色又叫做具体被观察者(Concrete Observable)角色。
● 抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在得到主题的通知时更新自己,这个接口叫做更新接口。
● 具体观察者(ConcreteObserver)角色:存储与主题的状态自恰的状态。具体观察者角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态 像协调。如果需要,具体观察者角色可以保持一个指向具体主题对象的引用。
其实抽象主题与具体主题是一个对象,书上这样分层的原因是为了体现多态原则,因为使用多态时可以不必知道具体类对象,从而达到保持这个具体类对象的引用(通过向下转型实现)。写过观察者模式的小伙伴可能都知道,抽象主题就是一个接口规范,至少定义了三个接口,接口一:添加观察者,主要将需要进行消息通知的观察者添加到列表进行保存
接口二:移除观察者,从列表中移除。移除的目的是为了防止内存泄漏。试想下,观察者 宋兵甲 订阅了 一个主题,某个时候,观察者 宋兵甲 不想再接收这个主题的消息通知了,有一天它发生交通事故不幸去世了,(这里理解为对象消失了),这个时候如果不主动从观察者列表中进行主动移除时,下一次需要发生通知信号时(假设宋兵甲订阅的主题 与本次发送的消息一致),也会通知 宋兵甲 这个观察者对象,
但是呢,由于 宋兵甲 对象消失 的原因 而它的引用又存在于观察者列表中,当遍历到这个对象时,主题也会把它当作普通的观察者进行消息通知,显然就有问题了, 因为宋兵甲这个对象的引用计数值不为0 所以它不会被系统进行回收,导致 宋兵甲 这个观察者 出现对象不存在,但是又不能被系统及时的回收现象,俗称 内存泄漏。
接口三:消息通知接口,根据相应的订阅主题对相应的观察者进行通知。
抽象/具体的 主题 类如下: 其实也可以对这个类进行扩展,扩展一下,把扩展的那个类定义为具体的主题 类即可。
这里为了演示这个思想,不做扩展处理,下同。
#import <Foundation/Foundation.h>
#import "Observer.h"
/**
观察者模式:
抽象主题(Subject)角色:抽象主题角色把所有对观察者对象的引用保存在一个聚集(比如ArrayList对象)里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象,抽象主题角色又叫做抽象被观察者(Observable)角色。
具体主题(ConcreteSubject)角色:将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色又叫做具体被观察者(Concrete Observable)角色。
抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在得到主题的通知时更新自己,这个接口叫做更新接口。
具体观察者(ConcreteObserver)角色:存储与主题的状态自恰的状态。具体观察者角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态 像协调。如果需要,具体观察者角色可以保持一个指向具体主题对象的引用。
本类为抽象的主题 类,主要用于多态机制
*/
@interface Subject : NSObject
/**
具体的观察者引用列表
*/
@property(strong,nonatomic) NSMutableArray* observersList;
/**
主题订阅器
*/
@property(strong,nonatomic) NSString* subjectRegister;
/**
添加观察者
@param observer 观察者对象
@param subject 观察者观察的主题
*/
-(void) registerObserver:(Observer*) observer forSubject:(NSString*) subject;
-(void) removeObserver:(Observer*) observer;
-(void) notifiObserver:(NSObject*) msg;
@end
#import "Subject.h"
@implementation Subject
-(instancetype)init{
if(self == [super init]){
self.observersList = [[NSMutableArray alloc] init];
self.subjectRegister = @"";
}
return self;
}
-(void) registerObserver:(Observer*) observer forSubject:(NSString*) subject{
[self.observersList addObject:observer];
self.subjectRegister = subject;
}
-(void) removeObserver:(Observer*) observer{
if([self.observersList containsObject:observer]){
[self.observersList removeObject:observer];
}
}
-(void) notifiObserver:(NSObject*) msg{
for(id obj in self.observersList){
if([self.subjectRegister isEqualToString:[obj subjectTag]]){
[obj update:msg];
}
}
}
@end
抽象观察者/具体观察者 类文件:
#import <Foundation/Foundation.h>
@interface Observer : NSObject
/**
主题标签
*/
@property(nonatomic,strong) NSString* subjectTag;
/**
构造器
@param subject 订阅主题
@return 实例对象
*/
-(instancetype) initWithSubject:(NSString*) subject;
-(void) update:(NSObject*) msg;
@end
#import "Observer.h"
@implementation Observer
-(instancetype) initWithSubject:(NSString*) subject{
if(self == [super init]){
self.subjectTag = subject;
}
return self;
}
-(void) update:(NSObject*) msg{
NSLog(@"观察者收到的对象是---%@",msg);
}
@end
测试类:
//创建主题
Subject* subject = [[Subject alloc] init];
//创建观察者
Observer* observer = [[Observer alloc] initWithSubject:@"A"];
Observer* observer2 = [[Observer alloc] initWithSubject:@"B"];
[subject registerObserver:observer forSubject:@"A"];
[subject registerObserver:observer2 forSubject:@"A"];
[subject notifiObserver:@"liu"];