(PubSub/SubScribe)订阅发布模式

什么是订阅发布模式

Publish/Subscribe模式使用了一个主题/ 事件通道,这个通道介于希望接收到通知的对象(订阅者)和激活事件的对象之间(发布者)。

订阅发布模式定义了一种一对多的依赖关系,让多个订阅者对象同时监听一个主题对象。这个主题对象在自身状态变化时,会通知所有订阅者对象,使它们能够自动更新自己的状态。

将一个系统分割成一系列相互协作的类有一个很不好的副作用,那就是需要维护相应对象间的一致性,这样会给维护、扩展和重用都带来不便。当一个对象的改变需要同时改变其他对象,而且它不知道具体有多少对象需要改变时,就可以使用订阅发布模式了

一个抽象模型有两个方面,其中一方面依赖于另一方面,这时订阅发布模式可以将这两者封装在独立的对象中,使它们各自独立地改变和复用。订阅发布模式所做的工作其实就是在解耦合。让耦合的双方都依赖于抽象,而不是依赖于具体,从而使得各自的变化都不会影响另一边的变化。
 

订阅发布针对前端的使用场景

记得redux是为什么而出现的吗?
就是针对复杂的数据状态的管理,当一个状态发生了变化,你可能要在多个地方更新这些变化,同时这些状态的变化,又会引起其他的状态的变化。
订阅发布就是解决这样的问题存在的。

有时候,你想监听一种状态,当在某种情况下,触发它,然后做一些相应的事,有点儿类似我们的自定义事件。订阅发布,也是解决这一类问题的利器。

优点

  • Observer模式和Publish/Subscribe模式鼓励我们努力思考应用程序不同部分之间的关系,可以用于将应用程序分解更小、更松散耦合的块,以改进代码管理和潜在的复用。
  • 在使用任何一种模式时,动态关系可以在观察者和目标之间存在。提供了很大的灵活性,当应用程序的不同部分紧密耦合时,这不是很容易实现的。
     

缺点

  • 从订阅者中解耦发布者,它有时会很难保证应用程序的特定部分按照我们期望的运行。
  • 订阅者非常无视彼此的存在,并对变换发布者产生的成本视而不见。由于订阅者和发布者之间的动态关系,很难跟踪以来更新。

基本的实现

基本的原理是维护一个对象,每次对这个对象进行遍历和更新。

function PubSub() {
    this.handles = {
        eventName: {
            eventsList: [],
            isOne: false,
        }
    }
}
PubSub.prototype.subscribe = function (eventName, callback) {
    let EventsList = [];
    if (arguments.length < 2) {
        throw new TypeError('arguments error');
    }
    if (Reflect.has(this.handles, eventName)) {
        EventsList = this.handles[eventName].eventsList;
    } else {
        this.handles[eventName] = {
            eventsList: [callback],
            isOne: false,
        };
    }
    EventsList.push(callback);
}

PubSub.prototype.notify = function (eventName, ...rest) {
    if (this.handles[eventName]) {
        let EventsList = this.handles[eventName].eventsList, i = 0, isOne = this.handles[eventName].isOne;
        if (EventsList) {
            for (; i < EventsList.length; i++) {
                EventsList[i].apply(this, rest)
            }
        }
        if (isOne) {
            this.unsubscribe(eventName)
        }
    }
    return this;
}

const myPub = new PubSub();

myPub.subscribe('event', function (data) {
    console.log('触发');
    console.log(data)
})
document.getElementById('btn').onclick = function () {
    myPub.notify('event', 123);
}

猜你喜欢

转载自blog.csdn.net/m0_60237095/article/details/121355532