观察者模式

内容纲要

观察者模式

目前有很多流行的技术用到了这个思想,比如Redux、mobx等,这里将多年前的ECMAScript代码改写成现代的ECMAScript代码。这里只做简单演示,请勿直接用于生产。

首先是派发者,派发者需要添加侦听、移出侦听和派发事件:

class Sender {

    private receiver: any[] = [];//接收者对象列表

    private eventMsg!: string;//发送的事件信息

    public constructor() {
    }

    public addEventListener(o: Receiver): void {

        this.receiver.push(o);//增加接收者

    }

    public removeEventListener(o: Receiver): void {

        var k: number;

        for (var i in this.receiver) {

            if (this.receiver[i] == o) {

                //遍历接收者数组,找到与传入的参数相同的接收者并把其在数组中的索引赋给k

                k = i;

                break;

            }

        }

        this.receiver.splice(k, 1);//从数组中删除这个接收者

    }

    public dispatchEvent(s: string): void {

        this.eventMsg = s;//事件信息传递

        this.notify();//通知方法

    }

    private notify(): void {

        var l: number = this.receiver.length;//接收者数组长度

        for (var i: number = 0; i < l; i++) {

            this.receiver[i].update(this.eventMsg);//接收者的更新方法

        }

    }

}

接着,创建一个接收者,接收者需要有一个初始的名称:

class Receiver {

    public name!: string;

    public Receiver(name: string) {

        this.name = name;

    }

    public tostring(): string {

        return this.name;//返回接收者名字

    }

    public update(s: string): void {

        trace(name + "收到" + s);

    }

}


function trace(msg: any): void {

    console.log(msg);

}

将发送者和接收者放在全局里即可,然后就可以使用了:

var sender: Sender = new Sender();//创建发送者

var receiver1: Receiver = new Receiver("A");

var receiver2: Receiver = new Receiver("B");//创建两个接收者

sender.addEventListener(receiver1);

sender.addEventListener(receiver2);//为发送者注册两个接收者

sender.dispatchEvent("消息");//发送消息

sender.removeEventListener(receiver1);//移除第一个接收者

sender.dispatchEvent("邮件");//发送"邮件"

如果需要在接受后处理,可以在接受后出发一个回调函数或者Promise:

public addEventListener(o: Receiver, callback: Function): void {

    this.receiver.push(o);//增加接收者

    callback(o);
}

//或者

public addEventListener(o: Receiver): Promise {

    this.receiver.push(o);

    return new Promise((resolve, reject) => {
        resolve(o);
    });

}

当然也可以直接使用Async,这里不再演示。

have enjoy! 🧐🧐🧐

作者:indeex

链接:https://indeex.cc

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


发表评论

您的电子邮箱地址不会被公开。