JavaScript 设计模式系列 - 观察者模式

本系列教程不会讲得特别深,经过案例,就带个入门,面试的时候,被问到能答出个因此来,在实际运用中,能把复杂的问题简单化就够了。javascript

概要:

你们应该常常听到工厂模式,单体模式,可是,可能你们可能第一次据说观察者模式,因此我设计模式系列第一篇就来说讲观察者模式。相信你们都用过鼠标悬停,按键等事件,其实他们就是观察者模式的例子。说重点,这种模式的实质就是你能够对程序中的某个对象的状态进行观察,而且在其发生改变时可以获得通知html

角色:

观察者模式中存在两种角色:观察者和被观察者,也能够叫作发布者和订阅者。java

做用:

例如,你在你每一个阶段,进行到必定阶段的时候,就要作一些事情,就能够利用观察者模式作一些相应的处理,不过多解释了。git

详解:

观察者模式中,并非一个对象调用另外一个对象的方法,而是一个对象订阅另外一个对象的特定活动并在状态改变后得到通知。当发生了一个重要的事件时,发布者将会通知全部订阅者而且可能常常以事件对象的形式传递消息。github

示例

为了加深理解,让咱们来看一个具体的例子,有三个报纸出版社,报社1、报社2、报社三,有两个订报人,分别是:订阅者1,订阅者2。在这里出版社就是被观察者,订报人就是观察者面试

被观察者
//观察者模式:对程序中某一个对象的进行实时的观察,当该对象状态发生改变的时候 进行通知
    //被观察者
    var Publish = function (name) {
        this.name = name;
        this.subscribers = []//数组中存着全部的订阅者(出版社名单),数组的元素都是函数类型
    }
    //publish的实例对象去发布消息的方法
    Publish.prototype.deliver = function (news) {
        var publish = this;//this就表明报社
        this.subscribers.forEach(function (item) {
            //循环subscribers数组中全部的订报人,为他们发布内容。
            item(news,publish);//每一个订阅者都收到了新闻(news),还有来自哪家报刊
        })
        return this;//为了方便,采用链式调用。
    }复制代码
观察者

订阅功能设计模式

//订阅者的方法,每个订阅者都是一个函数,在函数原型上扩展一个方法
    Function.prototype.subscribe = function (publish) {//出版社形参
        var sub = this;//取得当前订阅者这我的
        //不能同时订一家出版社同一份报纸,没意义
        //publish.subscribers//张三,李四,王五,名字可能重复
        //publish.subscribers数组里面有的人,不能再订阅
        //咱们使用ecma5里面的some方法,循环遍历数组的每个元素,执行一个函数,若是有相同的名字则返回true,不相同则返回false
        var alreadExists = publish.subscribers.some(function (item) {
            return item ===sub;
        })
        //若是出版社名单没有这我的,则加入其中
        if(!alreadExists){
            publish.subscribers.push(sub);
        }
        return this;//为了方便,采用链式调用。
    }复制代码

取消订阅数组

//具体的一个订阅者去取消订阅报纸的方法
                Function.prototype.unsubscribe = function(publish){
                    var sub = this;//取得当前订阅者这我的
                    // filter (过滤函数:循环便利数组的每个元素,执行一个函数若是不匹配,则删除该元素)
                    publish.subscribers = publish.subscribers.filter(function(item){
                        return item !== sub ;
                    });
                    return this;//为了方便,采用链式调用。
                };复制代码

好了,上面就已经作好了基本的准备的,咱们来作个小demo函数

//实例化发布者对象(报社对象)
        var pub1 = new Publish('报社一');
        var pub2 = new Publish('报社二');
        var pub3 = new Publish('报社三');

     //观察者
        var sub1 = function (news,pub) {
            console.log(arguments);
            document.getElementById('sub1').innerHTML +=pub.name+ news +'\n'
        }
        var sub2 = function (news,pub) {
            document.getElementById('sub2').innerHTML += pub.name+news+'\n'
        }
        var p1 = document.getElementById('pub1')
        var p2 = document.getElementById('pub2')
        var p3 = document.getElementById('pub3')
        //执行订阅方法
        sub1.subscribe(pub1).subscribe(pub2).subscribe(pub3)
        sub2.subscribe(pub1).subscribe(pub2).subscribe(pub3)

        //事件绑定
        p1.onclick = function () {
            pub1.deliver(document.getElementById('text1').value,pub1);
        }
        p2.onclick = function () {
            pub2.deliver(document.getElementById('text2').value,pub2);
        }
        p3.onclick = function () {
            pub3.deliver(document.getElementById('text3').value,pub3);
        }

        sub1.unsubscribe(pub1); //取消订阅复制代码

咱们来看看html代码段ui

<div class="col-lg-8">
    <div class="input-group"> <span id="pub1" class="input-group-addon"> 报社一 </span> <input v-model="user.name" type="text" class="form-control" id="text1"> </div> </div>
<div class="col-lg-8">
    <div class="input-group"> <span id="pub2" class="input-group-addon"> 报社二 </span> <input v-model="user.name" type="text" class="form-control" id="text2"> </div> </div>
<div class="col-lg-8">
    <div class="input-group"> <span id="pub3" class="input-group-addon"> 报社三 </span> <input v-model="user.name" type="text" class="form-control" id="text3"> </div> </div>

<div class="col-lg-8">
    订阅者一
    <textarea id="sub1" class="form-control" rows="5"></textarea>
    订阅者二:
    <textarea id="sub2"class="form-control" rows="5"></textarea>
</div>复制代码

不知道大家看懂了吗?没看懂能够随时留言,后续会出这一系列关于js设计模式的文章,大概有十章左右,包括单体模式,外观模式,中介者模式等等,由简单到难(欢迎留言这一篇看的感觉),因此欢迎你们指正,批评,督促。
github源码地址:github.com/Faithree/js…
参照案例书籍javascript模式

点赞是个人最大支持和鼓励

相关文章
相关标签/搜索