Although the ancient tune loves itself, many people don't talk about it today - Talking about the publish-subscribe model

The publish-subscribe mode, also known as the observer mode, defines a one-to-many relationship between objects. When the state of an object changes, all objects that depend on it will be notified. The general flow of implementing the Observer pattern

  • First specify the publisher (the object representing one)
  • Add a cache list to the publisher for storing callback functions to notify subscribers
  • When publishing a message, the publisher traverses the cache list and triggers the subscribers stored in it to return to the function in turn.

## Poor man's edition

let salesOffices = {}; // 售楼处 即 发布者
    salesOffices.clientList = []; // 缓存列表 存放订阅者的回调函数

    salesOffices.listen = (fn) => { // 增加订阅者
        salesOffices.clientList.push(fn); // 订阅的消息加进缓存列表
    }

    salesOffices.trigger = (arguments) => {
        salesOffices.clientList.forEach((fn) => { // arguments 是trigger函数接受的参数
            fn.call(this, arguments)
        })
    }

    salesOffices.listen((price) => {
        console.log('小明的消息' + price)
    })

    salesOffices.listen((price) => {
        console.log('小芳的消息' + price)
    })

    salesOffices.trigger(100)
    salesOffices.trigger(200)

Enhanced Edition

In the above code, Xiaoming and Fire will receive all the information. Next, we will add an identifier to the subscription function to mark user-specific information.

 /*
    * 假设小明只想接受100的消息
    * 那我们就要在添加订阅的时候加入标识
    * */
    let salesOffices = {}; // 售楼处 即 发布者
    salesOffices.clientList = {}; // 缓存列表 存放订阅者的回调函数

    salesOffices.listen = (key, fn) => { // 增加订阅者
        if (!salesOffices.clientList[key]) {
            salesOffices.clientList[key] = [];
        }
        salesOffices.clientList[key].push(fn); // 订阅的消息加进缓存列表
    }

    salesOffices.trigger = (arg1, ...arg2) => {
        let key = arg1;
        let fns = salesOffices.clientList[key];

        if (!fns || fns.length === 0) { // 没有订阅该消息
            return false;
        }

        fns.forEach((v) => {
            v.call(this, arg2) // arguments 指的是回调函数的
        })
    }

    salesOffices.listen(100,(price) => {
        console.log('小明的消息' + price)
    })

    salesOffices.listen(200,(price) => {
        console.log('小芳的消息' + price)
    })

    salesOffices.trigger(100, 2000) // 发布100
    salesOffices.trigger(200, 3000) // 发布200

The first principle of the design pattern is the separation of immutable and mutable, so we can abstract the observer object as a public class.

All-round version

    /*
    * 观察者类
    * */
    class Oberver {
        constructor () {
         this.clientList = {};
         this.stack = [];
        }
        listen (key, fn) { // key 事件名
            if (!this.clientList[key]) {
                this.clientList[key] = [];
            }

            this.clientList[key].push(fn);
            this.stack.forEach((v, index) => {
                v(key, index)
            })

        };
        trigger (arg1, ...arg2) {
            let key = arg1;
            let fns = this.clientList[key];

            if (!fns || fns.length === 0) {
                this.stack.push((key, index) => {
                    if (key == arg1) {
                        this.trigger(arg1, arg2);
                        this.stack.splice(index, 1);
                    }
                });
                return false;
            }

            fns.forEach(v=> {
                v.call(this, arg2)
            })
        }
    }
    // 删除订阅
    Oberver.prototype.remove = function (key, fn) {
        var fns = this.clientList[key];

        if (!fns) {
            return false;
        }
        if (!fn) {
            fns && (fns.length = 0); // 没有fn标识删除所有的订阅消息属于key的
        } else {
            fns = fns.filter(v => {
                return v != fn
            })
        }

        return fns;
    }
    
    /*
    * 添加具体的订阅发布
    * */
    var salesOffices = new Oberver();

    salesOffices.listen(100, function (prices) {
        console.log('我是小明我订阅了100的信息' + prices)
    })

    salesOffices.listen(200, function (proces) {
        console.log('我是小芳我订阅了200的信息' + proces)
    })

Applicable scene

The observer pattern is suitable for one-to-many business requirements, for example, many modules require login information, or communication between multiple encapsulated modules.

advantage

Time decoupling, object decoupling

shortcoming

It takes time to create subscribers, and subscribing to a message may not be of any use, but it's still in memory.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325054523&siteId=291194637