Object-c 观察者模式

观察者模式:具体的定义这里暂且不说了,书上有,只说说我个人的理解。

理解一:观察者模式角色分析:

          书上有角色分析如下:

      ●  抽象主题(Subject)角色:抽象主题角色把所有对观察者对象的引用保存在一个聚集(比如ArrayList对象)里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象,抽象主题角色又叫做抽象被观察者(Observable)角色。

  ●  具体主题(ConcreteSubject)角色:将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色又叫做具体被观察者(Concrete Observable)角色。

  ●  抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在得到主题的通知时更新自己,这个接口叫做更新接口。

  ●  具体观察者(ConcreteObserver)角色:存储与主题的状态自恰的状态。具体观察者角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态 像协调。如果需要,具体观察者角色可以保持一个指向具体主题对象的引用。

其实抽象主题与具体主题是一个对象,书上这样分层的原因是为了体现多态原则,因为使用多态时可以不必知道具体类对象,从而达到保持这个具体类对象的引用(通过向下转型实现)。写过观察者模式的小伙伴可能都知道,抽象主题就是一个接口规范,至少定义了三个接口,

    接口一:添加观察者,主要将需要进行消息通知的观察者添加到列表进行保存

    接口二:移除观察者,从列表中移除。移除的目的是为了防止内存泄漏。试想下,观察者 宋兵甲 订阅了 一个主题,某个时候,观察者 宋兵甲 不想再接收这个主题的消息通知了,有一天它发生交通事故不幸去世了,(这里理解为对象消失了),这个时候如果不主动从观察者列表中进行主动移除时,下一次需要发生通知信号时(假设宋兵甲订阅的主题 与本次发送的消息一致),也会通知 宋兵甲 这个观察者对象,

但是呢,由于 宋兵甲 对象消失 的原因 而它的引用又存在于观察者列表中,当遍历到这个对象时,主题也会把它当作普通的观察者进行消息通知,显然就有问题了, 因为宋兵甲这个对象的引用计数值不为0 所以它不会被系统进行回收,导致 宋兵甲 这个观察者 出现对象不存在,但是又不能被系统及时的回收现象,俗称 内存泄漏。


   接口三:消息通知接口,根据相应的订阅主题对相应的观察者进行通知。


  下面使用 2个类对象实现 这个模式,即抽象/具体的 主题 合并   抽象观察者/具体的观察者  两两合并

  抽象/具体的 主题 类如下: 其实也可以对这个类进行扩展,扩展一下,把扩展的那个类定义为具体的主题 类即可。

 这里为了演示这个思想,不做扩展处理,下同。



#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


.m文件

#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



.m文件 :

#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"];






  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值