【设计模式】实现一个简单的js发布-订阅者模式

一 概念
发布—订阅模式又叫观察者模式,它定义了对象间的一种一对多的关系,让多个观察者对象同时监听某一个主题对象,当一个对象发生改变时,所有依赖于它的对象都将得到通知。

二 现实中的发布订阅者模式
1.比如小红最近在淘宝网上看上一双鞋子,但是呢 联系到卖家后,才发现这双鞋卖光了,但是小红对这双鞋又非常喜欢,所以呢联系卖家,问卖家什么时候有货,卖家告诉她,要等一个星期后才有货,卖家告诉小红,要是你喜欢的话,你可以收藏我们的店铺,等有货的时候再通知你,所以小红收藏了此店铺,但与此同时,小明,小花等也喜欢这双鞋,也收藏了该店铺;等来货的时候就依次会通知他们;
在上面的故事中,可以看出是一个典型的发布订阅模式,卖家是属于发布者,小红,小明等属于订阅者,订阅该店铺,卖家作为发布者,当鞋子到了的时候,会依次通知小明,小红等,依次使用旺旺等工具给他们发布消息;

2.再比如,报社和读者也是典型的发布订阅者模式的一种,当报社一有新的报纸出版之后,就会告诉读者,我们新版报纸出来了,快来买啊。在这里,报社就是发布者,读者就是订阅者

三 代码实现
实现上面例子中 报社-读者 的发布订阅者模式

html

 <body>
    <input type="button" id="pub1" value="第一报社"><input type="text" id="txt1" value=''> <br>
    <input type="button" id="pub2" value="第二报社"><input type="text" id="txt2" value=''> <br>
    <input type="button" id="pub3" value="第三报社"><input type="text" id="txt3" value=''> <br>

    <textarea name="" id="sub1" cols="30" rows="10"></textarea>
    <textarea name="" id="sub2" cols="30" rows="10"></textarea>
</body>

//js
// 发布者
    var Publish = function(name) {
        this.name = name;
        this.subscribers = []; //接受所有的订阅者(每一个元素是函数类型fn的数组)
    }

    // Publish类的实例对象发布消息的方法
    Publish.prototype.deliver = function(news) {
        var publish = this;
        this.subscribers.forEach(function(fn) {
            // 把新消息发给一个订阅者
            fn(news, publish);
        });
        // 链式编程
        return this;
    }

    // 具体的一个订阅者去订阅报纸的方法
    Function.prototype.subscribe = function(publish) {
        var suber = this; //当前订阅者
        // 数组的some : 遍历数组中的元素,执行一个函数,有一个返回true、,整体返回true
        // 检查当前这个人是不是已经订阅过了
        var isExists = publish.subscribers.some(function(item) {
            return item === suber;
        });

        if (!isExists) {
            publish.subscribers.push(suber);
        }
        // 链式编程
        return this;
    }

    // 取消订阅的方法
    Function.prototype.unsubscribe = function(publish) {
        var suber = this;
        // filter  返回一个心数组, 
        // 去掉suber
        publish.subscribers = publish.subscribers.filter(function(item) {
            return item !== suber;
        });
        return this;
    }


 var pub1 = new Publish('第一报社');
    var pub2 = new Publish('第二报社');
    var pub3 = new Publish('第三报社');

    // 定义 2个订阅者
    var sub1 = function(news) {
        document.getElementById('sub1').innerHTML += arguments[1].name + '~~~' + news + '\n';
    }

    var sub2 = function(news) {
        document.getElementById('sub2').innerHTML += arguments[1].name + '~~~' + news + '\n';
    }

    // 执行订阅方法
    sub1.subscribe(pub1).subscribe(pub2).subscribe(pub3);
    sub2.subscribe(pub1).subscribe(pub2);

    // 事件绑定
    document.getElementById('pub1').onclick = function() {
        pub1.deliver(document.getElementById('txt1').value)
    }

    document.getElementById('pub2').onclick = function() {
        pub2.deliver(document.getElementById('txt2').value)
    }

    document.getElementById('pub3').onclick = function() {
        pub3.deliver(document.getElementById('txt3').value)
    }

    sub1.unsubscribe('pub1');
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值