IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    观察者模式与发布订阅模式 · 看不见我的美 · 是你瞎了眼

    馬腊咯稽发表于 2020-04-18 00:00:00
    love 0
    观察者模式与发布订阅模式

    观察者模式

    观察者模式就好个体奶农(Subject)和个人(Observers)的关系;奶农负责统计有多少人订了产品(Subscribe),个人都会有一个相同拿牛奶的方法(Event);奶农有新奶了就负责调用这个方法(Fire Event)。

    观察者模式是一对多的关系,多个观察者对应一个对象;当被观察对象更新时会通知所有观察者。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    
    // 观察者
    class Observer {
     constructor(name) {
     this.name = name;
     this.fn = null;
     }
     update() {
     console.log(`我是${this.name},听说被观察者更新了...`);
     typeof this.fn === 'function' && this.fn();
     }
    }
    // 被观察对象
    class Subject {
     list = []; // 保存所有观察者
     addObserver(observer) {
     // 添加新增的观察者
     this.list.push(observer);
     }
     notifyObservers() {
     // 通知观察者,我更新了
     this.list.forEach(item => {
     item.update();
     });
     }
    }
    let subject = new Subject();
    let zhangsan = new Observer('张三');
    let lisi = new Observer('李四');
    let wangwu = new Observer('王五');
    zhangsan.fn = () => {
     console.log('哈哈');
    };
    lisi.fn = () => {
     console.log('呵呵');
    };
    wangwu.fn = () => {
     console.log('嗨嗨');
    };
    // 添加订阅
    subject.addObserver(zhangsan);
    subject.addObserver(lisi);
    subject.addObserver(wangwu);
    // 通知更新
    subject.notifyObservers();
    

    发布订阅模式

    发布订阅模式就好像报社(Publishers)、邮局(Topic/Event Channel)和个人(Subscribers)的关系;报纸的订阅(Subscribe)和分发(Fire Event)是由邮局来完成的,报社只负责将报纸发送给邮局(Publish Topic/Event)。

    发布订阅模式是多对多的关系,可以有多个发布者多个观察者;每个发布者对应着多个观察者,每个观察者对应着多个发布者。

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    
    class Subscriber {
     constructor(name) {
     this.name = name;
     this.fn = null;
     }
     subscribe(channel) {
     channel.addSubscriber(this.name, this);
     }
     update() {
     console.log(`我是${this.name},我的快递到了...`);
     typeof this.fn === 'function' && this.fn();
     }
    }
    class Publisher {
     constructor(type) {
     this.type = type;
     }
     publishTopic(channel) {
     channel.notifySubscribers(this.type);
     }
    }
    class Channel {
     list = {};
     addSubscriber(type, subscriber) {
     let list = this.list[type] || [];
     list.push(subscriber);
     this.list[type] = list;
     }
     notifySubscribers(type) {
     this.list[type].forEach(item => {
     item.update();
     });
     }
    }
    let channel = new Channel();
    let zhangsan = new Subscriber('张三');
    let lisi = new Subscriber('李四');
    let wangwu = new Publisher('王五');
    let zhaoliu = new Publisher('赵六');
    zhangsan.subscribe(channel);
    lisi.subscribe(channel);
    wangwu.publishTopic(channel);
    zhaoliu.publishTopic(channel);
    

    回归 Vue

    对于响应式对象,Vue 会在对象属性的 getter 中收集属性对应的依赖,在对象属性的 setter 中通知对应依赖进行更新;一个数据对象对应多个依赖,数据是被观察目标,视图、计算属性、侦听器这些是观察者/依赖者。

    参考

    • 不好意思,观察者模式跟发布订阅模式就是不一样
    • 介绍下观察者模式和订阅发布模式的区别


沪ICP备19023445号-2号
友情链接