观察者模式和发布订阅模式(上)

观察者模式

定义:观察者模式(Observer Pattern):定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。

其中有两个定义需要明确,被观察者和观察者。通常来说,这两者是一对多的,也有多对多的情景。

在网页开发中,被观察者通常是数据源,不论是内存数据,还是持久化数据,又或者是接口返回的数据,都可以作为被观察者。它一旦改变,就去改变依赖于它的节点。

观察者有很多可能,针对于网页开发,我们常常认为dom节点是观察者,一旦节点的监视的数据源发生变化,节点也执行更新方法。当然不限于此,也有可能是一个事件,一次计数等等。

接下来用js写一个简单的观察者模式的例子:

// 发布类
class Subject {
  constructor (data) {
    this.obList = [];
    this.data = data;
  }
  add (ob) {
    if (arguments.length >= 1) {
      Array.from(arguments).forEach(item => this.obList.push(item));
    }
  }
  remove (ob) {
    let i = this.obList.findIndex(ele => ele === ob);
    if (i >= 0) {
      this.obList.splice(i, 1);
    }
  }
  notify () {
    this.obList.forEach((item) => {
      item.update(this.data);
    })
  }
}

// 观察者类
class Observer {
  constructor (id) {
    this.id = id;
  }
  update (data) {
    console.log(‘observer ‘ + this.id + ‘: ‘ + data + ‘;‘);
  }
}

function test() {
  let sub = new Subject(‘test‘);

  let ob1 = new Observer(1);
  let ob2 = new Observer(2);
  let ob3 = new Observer(3);

  sub.add(ob1, ob2, ob3);

  sub.notify();

  sub.remove(ob2);

  sub.notify();
}

test();

结果为:

observer 1: test;
observer 2: test;
observer 3: test;
observer 1: test;
observer 3: test;

这里简单定义了一个发布类和一个观察类,发布者维护一个观察者列表,每次数据变化后,依次通知所有在观察者列表里的观察者。

代码很简单,可以执行在控制台或者node里跑一下。

但是这样的耦合很深,观察者和发布者不能有其他的表现,很死板,我们可以继续抽象一下。

先画个类图:

借助于TypeScript,我们可以有如下的发布者和观察者定义。

abstract class Observer {
    abstract update();
}

abstract class Subject {
    protected obList: ObserverList;
    abstract notify();
}

ObserverList则可以实现如下:

class ObserverList {
    private list: Array<Observer>;
    constructor () {
        this.list = [];
    }
    add (ob: Observer) {
        this.list.push(ob);
    }

    remove (ob: Observer) {
        if (this.list.indexOf(ob) > -1) {
            this.list.splice(this.list.indexOf(ob), 1);
        }
    }

    empty () {
        this.list = [];
    }

    public each () {
        this.list.forEach(item => {
            item.update();
        })
    }
}

接下来实现两个实体类:

// 实体发布类
class ConcreteSubject extends Subject {
    protected obList = new ObserverList();

    private _data: string;

    constructor (defaultData: string) {
        super();
        this._data = defaultData;
    }

    set data (newVaule) {
        this._data = newVaule;
    }
    get data () {
        return this._data;
    }

    add (ob: Observer) {
        this.obList.add(ob);
    }
    remove (ob: Observer) {
        this.obList.remove(ob);
    }
    notify () {
        this.obList.each()
    }
}

// 可以指定发布者的观察者类
class ConcreteObserver extends Observer {
    readonly _id;
    private sub;

    constructor (id, sub) {
        super();
        this._id = id;
        this.sub = sub;
    }

    get id () {
        return this._id;
    }

    update () {
        console.log(‘concrete observer ‘ + this.id + ‘: ‘ + this.sub.data);
    }
}

跑一下测试代码:

let sub = new ConcreteSubject(‘test‘);

let ob1 = new ConcreteObserver(1, sub);
let ob2 = new ConcreteObserver(2, sub);
let ob3 = new ConcreteObserver(3, sub);

sub.add(ob1)
sub.add(ob2)
sub.add(ob3)

sub.notify();

上面的发布类,使用add、remove等方法来处理观察者列表,通过notify方法,则去通知观察者们,可以去执行update方法了。

观察者和被观察者,仍然耦合比较深,所以又有人提出来发布订阅模式,维护一个事件中心,来处理多个观察者和被观察者的关系,不让他们直接耦合在一起。下一篇对发布订阅做解析。

原文地址:https://www.cnblogs.com/liuyongjia/p/9404627.html

时间: 2024-10-07 19:52:55

观察者模式和发布订阅模式(上)的相关文章

观察者模式 vs 发布-订阅模式

我曾经在面试中被问道,_“观察者模式和发布订阅模式的有什么区别?” _我迅速回忆起“Head First设计模式”那本书: 发布 + 订阅 = 观察者模式 “我知道了,我知道了,别想骗我” 我微笑着回答:“没有区别,它们是一样的.” 但是面试官笑了,“不,它们不一样.” 我当时的表情: 所以是我错了吗? 之后我回到家打开google查找答案.这篇文章就是我google后的总结. 在深入探讨区别之前,我们先来讨论下“观察者模式”和“发布订阅模式”. 观察者设计模式: 我认为大多数人都会同意观察者模

观察者模式与发布订阅模式的区别

观察者模式是软件设计模式的一种.在此种模式中,一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知.这通常透过呼叫各观察者所提供的方法来实现.此种模式通常被用来实时事件处理系统. 发布/订阅模式(Pub/Sub)是一种消息模式,它有 两个参与者 :  发布者和订阅者 .发布者向 某个信道发布一条消息,订阅者绑定这个信道,当有消息发布至信道时就会 接收到一个通知.最重要的一点是, 发布者和订阅者是完全解耦的,彼此并不知晓对方 的存在.两者仅仅共享一个信道名称. 从定义上可

设计模式--观察者模式(发布订阅模式)

观察者模式又叫做发布—订阅模式,是我们最常用的设计模式之一.它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知和更新. 观察者模式提供了一个订阅模型,其中对象订阅事件并在发生时得到通知,这种模式是事件驱动的编程基石,它有利益于良好的面向对象的设计. 从上面的话语我们可以得知,观察者模式主要动力是促进形成松散耦合(解耦). 设计思路: 首先先声明一个观察者对象 // 注册观察者对象 var Observer = (function (){ var Oms

观察者模式和发布订阅模式

最近项目里,写了一个通知服务,具备处理短信.电邮.站内信的能力.但我做多了一点,就是可以通过配置选择它的能力,比如只具备处理短信或者具备点油.站内信的能力. 我画了一个简单的图 图中的 Dispatcher是一个Message的中转器,它负责投递给最终的 SMS.Email.Website处理器处理.但是 Dispatcher里,我使用了硬编码来内置 SMS.Email.Website处理器(尽管我加了些判断,来区别此能力是否开启),但它的耦合太高. 所以能够如何优化呢? 观察者模式 观察者模式

观察者模式和发布/订阅模式的区别

在事件总线(EventBus)的架构设计中,用到了发布/订阅模式,但发现和观察者模式挺接近,有时容易发生混淆,现试图分清一下他们的关系. 观察者模式的角色为观察者(observer)和主题(subject)对象,observer需要观察subject时,需先到subject里面进行注册(subject对象持有observer对象的集合句柄),然后,当subject对象的内部状态发生变化时,把这个变化通知所有的观察者. 发布.订阅模式的角色为发布者(publisher)和订阅者(subscribe

观察者模式Vs发布订阅模式

1)观察者模式 观察者模式通俗的讲就是我们平事件调用(click/change等等) 大家先看这个图片.我们被观察者Subject(监听某个事件)发生改变时,观察者Observer监听到没改变做出调整.最大的特点是实现了松耦合(如何理解松耦合呢?个人认为就是当Subject 发生给变时,我们有一套对应的Observer集合,当Subject中的模块1 给变时对应的Observer1做出反应,当Subject中的模块2 给变时对应的Observer2做出反应...,不必全部都是一一对应,来实现松耦

C#设计模式--观察者模式(发布-订阅模式)

0.C#设计模式--简单工厂模式 1.C#设计模式--工厂方法模式 2.C#设计模式--抽象工厂模式 3.C#设计模式--单例模式 4.C#设计模式--建造者模式 5.C#设计模式--原型模式 6.C#设计模式--设配器模式 7.C#设计模式--装饰器模式 8.C#设计模式--代理模式 9.C#设计模式--外观模式 10.C#设计模式--桥接模式 设计模式: 观察者模式(Observer Pattern) 简单介绍: 观察者模式(Observer Pattern)是设计模式中行为模式的一种,它解

C# 委托和事件 与 观察者模式(发布-订阅模式)讲解 by天命

使用面向对象的思想 用c#控制台代码模拟猫抓老鼠 我们先来分析一下猫抓老鼠的过程 1.猫叫了 2.所有老鼠听到叫声,知道是哪只猫来了 3.老鼠们逃跑,边逃边喊:"xx猫来了,快跑啊!我是老鼠xxx" 一  双向耦合的代码 首先需要一个猫类Cat 一个老鼠类Rat 和一个测试类Program 老鼠类的代码如下 //老鼠类 public class Rat { public string Name { get; set; } //老鼠的名字 public Cat MyCat { get;

JS的发布订阅模式

JS的发布订阅模式 这里要说明一下什么是发布-订阅模式 发布-订阅模式里面包含了三个模块,发布者,订阅者和处理中心.这里处理中心相当于报刊办事大厅.发布者相当与某个杂志负责人,他来中心这注册一个的杂志,而订阅者相当于用户,我在中心订阅了这分杂志.每当发布者发布了一期杂志,办事大厅就会通知订阅者来拿新杂志.这样在结合下面的图应该很好理解了. 其实就是将发布者和订阅者解耦了,在实际开发中,经常会遇到某个方法内处理很多的逻辑,最简单的就是直接在方法内直接写.这种是高度耦合的面向过程的写法.对于代码维护