美文网首页
观察者模式(Observer Pattern)

观察者模式(Observer Pattern)

作者: iOS_学渣 | 来源:发表于2019-11-28 11:53 被阅读0次

    观察者模式:定义了对象之间一对多的依赖,那么在一个对象状态改变时,它所有依赖的对象都会收到通知并自动更新。

    观察者模式是众多的行为性模式之一。观察者模式定义上来看就很简单。在iOS中NSNOtifycationCenter,KVO,就是用观察者模式来实现的。当然这里我们不会直接拿iOS的API,而是分析下它的内部逻辑,方便理解。所以如果是真心想理解观察者模式的iOS开发者,还是可以好好看看它的内部实现。

    观察者模式

    这个类图是从HeadFirst中截取的,上面的描述很清晰。观察者由主题Subject)和观察者(Observer)组成。主题在改变时通知观察者做出更新。

    举个栗子
    农场主种了一棵很特别的苹果树,等待着结果。
    等待结果的不仅仅是农场主,当地的商贩也看中了这棵果树,也等着它开花结果。

    那这里有一个主题(subject)果树
    有两个观察者分别是农场主和商贩。农场主和商贩不可能每天都去看啥时候成熟,所以不如让果树能自动更新它的数据给农场主和商贩。

    观察者协议

    #import <Foundation/Foundation.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    @protocol ObserverObject <NSObject>
    
    -(void)update:(NSDictionary *)userInfo;
    
    @end
    
    NS_ASSUME_NONNULL_END
    

    被观察者协议(subject)

    #import <Foundation/Foundation.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    @protocol ObServerProtocol <NSObject>
    
    @property(nonatomic, strong) NSMutableArray * observers;
    
    -(void)registerObserver:(id)observer;
    
    -(void)removeObserver:(id)observer;
    
    -(void)notifyObserver;
    
    @end
    
    NS_ASSUME_NONNULL_END
    

    苹果树的实现(ConcreteSubject)

    #import "AppleTree.h"
    #import "ObserverObject.h"
    
    @interface AppleTree ()
    
    @property(nonatomic, assign)float height;
    
    @property(nonatomic, assign)BOOL isOpen;
    
    @property(nonatomic, assign)BOOL isRipen;
    
    @end
    
    @implementation AppleTree
    @synthesize observers = _observers;
    
    
    -(instancetype)init  {
        
        if (self = [super init]) {
            
            _observers = [NSMutableArray array];
            [self grewUp];
            
        }return self;
    }
    
    - (void)notifyObserver {
        //循环遍历观察者对象,并对观察者对象发出通知
        [_observers enumerateObjectsUsingBlock:^(id<ObserverObject> _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            NSMutableDictionary * temp  = [NSMutableDictionary dictionary];
            temp[@"height"] = @(_height);
            temp[@"isOpen"] = @(_isOpen);
            temp[@"isRipen"] = @(_isRipen);
            [obj update:temp];
        }];
        
    }
    
    - (void)registerObserver:(nonnull id)observer {
        
        if (![_observers containsObject:observer]) {
            [_observers addObject:observer];
        }
    }
    
    - (void)removeObserver:(nonnull id)observer {
        
        if ([_observers containsObject:observer]) {
            [_observers removeObject:observer];
        }
    }
    //模拟一段生长过程
    -(void)grewUp {
        
        [NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {
            _height += 0.2;
            if (_height >= 1.2 && _height < 1.5) _isOpen = true;
            else _isOpen = false;
            
            if (_height > 2.0) {
                _isRipen = YES;
            }
            [self notifyObserver];
        }];
    }
    
    @end
    
    

    农场主实现(ConcreteObserver)

    #import "Farmer.h"
    
    @implementation Farmer
    
    -(instancetype)initWithAppleTree:(AppleTree *)appleTree {
        
        if (self = [super init]) {
            _appleTree = appleTree;
            [_appleTree registerObserver:self];
        }return self;
    }
    
    
    -(void)update:(NSDictionary *)userInfo {
        
        float height = [userInfo[@"height"] floatValue];
        BOOL isOpen = [userInfo[@"isOpen"] boolValue];
        NSLog(@"当前树高%f",height);
        if (isOpen) {
            
            NSLog(@"已经开花了,开始施肥");
        }
    }
    
    @end
    
    

    商贩的实现 (ConcreteObserver)

    #import "Trader.h"
    
    @implementation Trader
    
    -(instancetype)initWithAppleTree:(AppleTree *)appleTree {
        
        if (self = [super init]) {
            
            _appleTree = appleTree;
            
            [_appleTree registerObserver:self];
        }return self;
    }
    
    -(void)update:(NSDictionary *)userInfo {
        
        BOOL isRipen = [userInfo[@"isRipen"] boolValue];
        if (isRipen) {
            NSLog(@"苹果成熟了,可以收购了");
        }
    }
    
    @end
    

    具体调用

    tree = [[AppleTree alloc] init];
    farmer = [[Farmer alloc] initWithAppleTree:tree];
    trader =  [[Trader alloc] initWithAppleTree:tree];
    

    优点

    1.观察者模式是基于抽象耦合的。
    2.观察者模式建立起了一套触发机制,可以在对象改变的时候让观察者响应。

    缺点

    1.如果一个对象有太多的直接或者间接的观察者,那么将所有的观察者都通知到会很耗时间
    2.观察者并不知道主题对象是如何变化的(也可以作为它的优点)

    相关文章

      网友评论

          本文标题:观察者模式(Observer Pattern)

          本文链接:https://www.haomeiwen.com/subject/jevvwctx.html