美文网首页
观察者模式(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