iOS原生观察者模式&重新设计观察者模式

2017-09-14  本文已影响38人  Jeff_Kitty

       原生KVO的实现依赖于强大的runtime运行时机制,实现原理大致为:当观察某对象A的属性时,会动态的创建这个类的子类,并为这个新的子类重写了Setter方法,在这个Setter方法里面负责通知观察者属性变化的情况。

       前段时间面试的时候,面试官问我,如果不用系统的KVO模式,自己来实现一种设计模式,当时可能由于紧张,一下子没反应过来,最后结果可想而知,现在想来,对比现在所在的外包公司的种种不公平待遇,总结下来一句话,肚子里没货还真不行。

      闲话不多扯,先来简单说一下如何自己实现NSNotificationCenter通知模式,然后,细聊如何通过协议实现KVO,不同于原生KVO的实现方案。

      通知中心实现方案,首先进行角色划分,一个单例类A+抽象协议接口(包含接收到通知后实现的接口和发出通知的接口)Protocol+具体的实现类B;

        客户端:    A   包含属性数组  ,B遵循Protocol,实现协议方法,A数组持有B对象,当A发出通知时,取出数组中的B对象,通过运行时,让B实现协议方法,从而达到通知的目的。

这里,我们重点看一下KVO的实现方案,首先进行角色划分:

第一步 : 抽象出接口:所有观察者必须遵循这个协议

// 抽象观察者Observer

@protocol Observer

- (void)update:(Observable *)o msg:(NSObject *)msg;

@end

第二步:定义一个基类Observable,所有被观察者对象都必须继承于Observable基类

// 注册观察者- (void)addObserver:(id)o;                                          
// 删除观察者- (void)deleteObserver:(id)o;

// 删除所有观察者
- (void)deleteObservers;

// 观察者数量
- (NSInteger)countObserver;

// 通知
- (void)notifyObservers;

- (void)notifyObservers:(NSObject *)msg;

// 更新数据
- (void)setChanged;

// 取消更新
- (void)clearChanged;

// 获取更新状态
- (BOOL)hasChanged;

Observable.m文件实现:

#import "Observable.h"@interface Observable()
@property (nonatomic,strong) NSMutableArray *obsArray;
@property (nonatomic,assign) BOOL changed;
@end

// 被观察者
@implementation Observable
- (instancetype)init{ 
       if (self = [super init]) {   
     _obsArray = [NSMutableArray array];       
 _changed = NO;    } 
  return self;}

// 注册观察者
- (void)addObserver:(id)o {    [_obsArray addObject:o];}
// 删除观察者
- (void)deleteObserver:(id)o {    [_obsArray removeObject:o];}
// 删除所有观察者
- (void)deleteObservers {    [_obsArray removeAllObjects];}
// 观察者数量
- (NSInteger)countObserver {    return _obsArray.count;}
- (void)notifyObservers {    [self notifyObservers:nil];}
- (void)notifyObservers:(NSObject *)msg
{   
    if (!_changed) {        return ;    }   
    [self clearChanged];   
     for (idobj in _obsArray) {
[obj update:self msg:msg];
}
}

// 更新数据
- (void)setChanged {
_changed = YES;
}

// 取消更新
- (void)clearChanged {
_changed = NO;
}

// 获取更新状态
- (BOOL)hasChanged {
return _changed;
}

客户端实现:

WXObservable *observable = [WXObservable new];

[observable addObserver:[CoffeeObserver new]];

[observable addObserver:[SimpleObserver new]];

[observable setTitle:@"思维的切换"];

[observable push];

[observable push];

[observable push];

上一篇下一篇

猜你喜欢

热点阅读