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

观察者模式(Observer Pattern)

作者: long弟弟 | 来源:发表于2022-09-18 00:08 被阅读0次

观察者模式,发布订阅模式(Publish-Subscribe Design Pattern)

意图:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

在对象之间定义一个一对多依赖,当一对象状态改变的时候,所有依赖的对象都会自动收到通知。

观察者模式.jpg

角色和职责

  1. Subject 主题,目标,被观察者
    被观察的对象,当需要被观察的状态发生变化时,需要通知队列中所有观察者对象。
    Subject需要维持(添加、删除、通知)一个观察者对象的队列列表
  2. ConCreteSubject 具体目标
    被观察者的具体实现,包含一些基本的属性状态及其他操作
    将有关状态存入各ConCreteObserver
    当它的状态发生改变时,向它的各个观察者发出通知
  3. Observer 观察者
    接口或抽象类,当Subject的状态发生变化时,Observe对象将通过一个callback函数得到通知
    为那些在目标发生改变时需获得通知的对象定义一个更新接口
  4. ConCreteObserve 具体观察者
    存储有关状态,这些状态应与目标的状态保持一致
    观察者的具体实现,得到通知后将完成一些具体的业务逻辑处理

代码示例

描述场景:定义了一种一对多的关系,让多个观对象(公司员工)同时监听一个主题对象(秘书),主题对象状态发生变化时,会通知所有的观察者,使它们能够更新自己。

#import <Foundation/Foundation.h>
@class Secretary;
//上班玩游戏的人,Observer观察者
@interface Player : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, strong) Secretary *secretary;
@end
@implementation Player
- (instancetype)initWithName:(NSString *)name AndSecretary:(Secretary *)secretary {
    if (self = [super init]) {
        self.name = name;
        self.secretary = secretary;
    }
    return self;
}
- (void)update:(NSString *)info {
    NSLog(@"%@观察到了%@", self.name, info);
}
@end

//秘书 看见老板来了通知上班玩游戏的人 Subject被观察者
@interface Secretary : NSObject
@property (nonatomic, copy) NSString *action;
@property (nonatomic, strong) NSMutableArray *observers;
@end
@implementation Secretary
- (instancetype)init {
    if (self = [super init]) {
        self.observers = [NSMutableArray array];
    }
    return self;
}
- (void)addObserver:(Player *)player {
    [self.observers addObject:player];
}
- (void)notify:(NSString *)info {
    //给所有的观察者发送情报
    for (Player *player in self.observers) {
        [player update:info];
    }
}
@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Secretary *secretary = [[Secretary alloc] init];
        Player *p1 = [[Player alloc] initWithName:@"张三" AndSecretary:secretary];
        Player *p2 = [[Player alloc] initWithName:@"李四" AndSecretary:secretary];
        [secretary addObserver:p1];
        [secretary addObserver:p2];
        [secretary notify:@"老板来了"];
        [secretary notify:@"老板走了"];
    }
    return 0;
}
/*
张三观察到了老板来了
李四观察到了老板来了
张三观察到了老板走了
李四观察到了老板走了
*/

用处

  • 侦听事件驱动程序设计中的外部事件
  • 侦听/监视某个对象的状态变化
  • 发布者/订阅者(publisher/subscriber)模型中,当一个外部事件(新的产品,消息的出现等等)被触发时,通知邮件列表中的订阅者。

iOS中,KVO通知就是观察者模式。

优点

  1. 观察者和被观察者是抽象耦合的。
    被观察者仅知道它有一系列观察者,每个都符合抽象的Observer类的简单接口。被观察者不知道任何一个观察者属于哪一个具体的类。这样观察者和被观察者之间的耦合是抽象的和最小的。
  2. 支持广播通信
    被观察者发送的通知不需要指定接收者,通知被自动广播给所有已向该被观察者对象登记的有关对象。处理还是忽略一个通知取决于观察者。

缺点

  • 意外更新
    因为一个观察者并不知道其它观察者的存在,它可能对改变被观察者的最终代价一无所知。

题外话

观察者模式和中介者模式都是为了实现参与者之间的解耦,简化交互。两者的不同在于应用场景上。在观察者模式的应用场景中,参与者之间的交互比较有条理,一般都是单向的,一个参与者只有一个身份,要么是观察者,要么是被观察者。而在中介模式的应用场景中,参与者之间的交互关系错综复杂,既可以是消息的发送者也可以同时是消息的接收者。
除此之外,如果一个参与者状态改变,要求其他参与者执行操作有一定的先后顺序,这时候,中介模式可以利用中介类,通过先后调用不同参与者的方法,来实现顺序操作,而观察者模式是无法实现这样的顺序要求的。

相关文章

网友评论

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

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