国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

javascript設(shè)計(jì)模式學(xué)習(xí)筆記之發(fā)布-訂閱模式

klivitamJ / 1677人閱讀

摘要:發(fā)布訂閱模式定義對(duì)象間的一種一對(duì)多的依賴關(guān)系當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí)所有依賴于它的對(duì)象都將得到通知簡(jiǎn)單實(shí)現(xiàn)定義發(fā)布者緩存列表存放訂閱者的回調(diào)函數(shù)定義訂閱者發(fā)布消息測(cè)試訂閱者價(jià)格訂閱者價(jià)格發(fā)布消息上面的實(shí)現(xiàn)方式導(dǎo)致了每個(gè)訂閱者都會(huì)收到發(fā)布

發(fā)布-訂閱模式

定義對(duì)象間的一種 一對(duì)多 的依賴關(guān)系, 當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí), 所有依賴于它的對(duì)象都將得到通知

簡(jiǎn)單實(shí)現(xiàn)

    // 定義發(fā)布者
    var salesOffices = {};

    // 緩存列表, 存放訂閱者的回調(diào)函數(shù)
    salesOffices.clientList = [];
    
    // 定義訂閱者
    salesOffices.listen = function (fn) {
        this.clientList.push(fn);
    }

    // 發(fā)布消息
    salesOffices.trigger = function () {
        for (var i = 0, fn; fn = this.clientList[i++];) {
            fn.apply(this, arguments)
        }
    }
    
    /*** 測(cè)試 ***/
    
    // 訂閱者1
    salesOffices.listen(function (price, squareMeter) {
        console.log("價(jià)格=" + price);
        console.log("squareMeter= " + squareMeter);
    });

    // 訂閱者2
    salesOffices.listen(function (price, squareMeter) {
        console.log("價(jià)格=" + price);
        console.log("squareMeter= " + squareMeter);
    });

    // 發(fā)布消息
    salesOffices.trigger(2000, 80);
    salesOffices.trigger(3000, 100);

上面的實(shí)現(xiàn)方式, 導(dǎo)致了, 每個(gè)訂閱者都會(huì)收到發(fā)布者發(fā)布的消息

    // 定義發(fā)布者
    var salesOffices = {};

    // 緩存列表, 存放訂閱者的回調(diào)函數(shù)
    salesOffices.clientList = {};

    // 定義訂閱者 (增加緩存, 增加標(biāo)示 key )
    salesOffices.listen = function (key, fn) {
        if (!this.clientList[key]) {
            this.clientList[key] = [];
        }
        this.clientList[key].push(fn);
    }

    // 發(fā)布消息
    salesOffices.trigger = function () {

        var key = Array.prototype.shift.call(arguments),
            fns = this.clientList[key];

        if (!fns || fns.length === 0) {
            return false;
        }

        for (var i = 0, fn; fn = fns[i++];) {
            fn.apply(this, arguments)
        }
    }
提煉發(fā)布-訂閱模式
    // 核心事件
    var event = {
        clientList: {},
        listen: function (key, fn) {
            if (!this.clientList[key]) {
                this.clientList[key] = [];
            }
            this.clientList[key].push(fn);
        },
        trigger: function () {
            var key = Array.prototype.shift.call(arguments),
                fns = this.clientList[key];

            if (!fns || fns.length === 0) {
                return false
            }

            for (var i = 0, fn; fn = fns[i++];) {
                fn.apply(this, arguments);
            }
        }
    }
    
    // 取消訂閱消息
    event.remove = function (key, fn) {
        var fns = this.clientList[key];

        if (!fns) {
            return false;
        }

        if (!fn) {
            // 沒有傳入fn 取消key對(duì)應(yīng)的所有的訂閱
            fns && (fns.length = 0);
        } else {
            // 傳入fn 刪除對(duì)應(yīng)的fn
            for (var l = fns.length - 1; l >= 0; l--) {
                var _fn = fns[l];
                if (_fn === fn) {
                    fns.splice(l, 1)
                }
            }
        }
    }
    
    // 給任何對(duì)象動(dòng)態(tài)增加發(fā)布-訂閱功能
    var installEvent = function (obj) {
        for (var key in event) {
            if (event.hasOwnProperty(key)) {
                obj[key] = event[key];
            }
        }
    }
    
    /*** 測(cè)試 ***/
    var salesOffices = {};

    installEvent(salesOffices);

    // 訂閱者1
    salesOffices.listen("squareMeter80", function (price) {
        console.log("價(jià)格=" + price);
    });

    // 訂閱者2
    salesOffices.listen("squareMeter100", function (price) {
        console.log("價(jià)格=" + price);
    });

    // 發(fā)布消息
    salesOffices.trigger("squareMeter80", 20000);
    salesOffices.trigger("squareMeter100", 30000);

登錄案例

    // 登錄成功, 發(fā)布成功消息
    $.ajax("http://xxx.com/login", function (data) {
        login.trigger("loginSuccess", data);
    });

    // 這種寫法也很好
    var header = (function () {
        // 訂閱消息
        login.listen("loginSuccess", function (data) {
            header.setAvatar(data);
        })
        return {
            setAvatar: function (data) {
                console.log("header 模塊拿到用戶信息")
            }
        }
    })();

以上寫法會(huì)有三個(gè)問題

需要一個(gè)類似"中介者"的角色, 把發(fā)布者和訂閱者聯(lián)系起來(通過 全局的 Event 來解決)

以上必須先訂閱, 才能發(fā)布

全局命名的沖突

實(shí)現(xiàn)類似 Event 的發(fā)布-訂閱模式

優(yōu)點(diǎn)1: 時(shí)間上的解耦,

優(yōu)點(diǎn)2: 對(duì)象之間的解耦

缺點(diǎn)1: 創(chuàng)建訂閱者本生要消耗內(nèi)存和時(shí)間

缺點(diǎn)2: 弱化了對(duì)象之間的聯(lián)系之后, 對(duì)象之間的必要聯(lián)系也被埋沒

    var Event = (function() {
        var global = this,
            Event,
            _default = "default";

        Event = function () {
            var _listen,
                _trigger,
                _remove,
                _slice = Array.prototype.slice,
                _shift = Array.prototype.shift,
                _unshift = Array.prototype.unshift,
                namespaceCache = {},
                _create,
                find,
                each = function(arr, fn) {
                    var ret;
                    for (var i = 0, l = arr.length; i < l; i++) {
                        var n = arr[i];
                        ret = fn.call(n, i, n);
                    }
                    return ret;
                };

            _listen = function (key, fn, cache) {
                if (!cache[key]) {
                    cache[key] = [];
                }
                cache[key].push(fn);
            };

            _remove = function (key, cache, fn) {
                if (cache[eky]) {
                    if (fn) {
                        for (var i = cache[key].length - 1; i >= 0; i--) {
                            if (cache[key][i] === fn) {
                                cache[key].splice(i, 1);
                            }
                        }
                    } else {
                        cache[key] = [];
                    }
                }
            }

            _trigger = function () {
                var cache = _shift.call(arguments),
                    key = _shift.call(arguments),
                    args = arguments,
                    _self = this,
                    ret,
                    stack = cache[key];

                if (!stack || !stack.length) {
                    return;
                }

                return each(stack, function () {
                    return this.apply(_self, args);
                })
            };

            _create = function (namespace) {
                namespace = namespace || _default;
                var cache = {},
                    offlineStack = [],
                    ret = {
                        listen: function (key, fn, last) {
                            _listen(key, fn, cache);

                            if (offlineStack === null) {
                                return;
                            }

                            if (last === "last") {
                                offlineStack.length && offlineStack.pop()();
                            } else {
                                each(offlineStack, function () {
                                    this();
                                })
                            }

                            offlineStack = null;
                        },

                        one: function (key, fn, last) {
                            _remove(key, fn, cache);
                            this.listen(key, fn, last);
                        },

                        remove: function (key, fn) {
                            _remove(key, cache, fn);
                        },

                        trigger: function () {
                            var fn,
                                args,
                                _self = this;

                            _unshift.call(arguments, cache);

                            args = arguments;

                            fn = function () {
                                return _trigger.apply(_self, args);
                            }

                            if (offlineStack) {
                                return offlineStack.push(fn);
                            }

                            return fn();
                        }
                    };

                return  namespace
                            ? (namespaceCache[namespace]
                                ? namespaceCache[namespace]
                                : namespaceCache[namespace] = ret)
                            : ret
            }

            return {
                create: _create,
                one: function (key, fn, last) {
                    var event = this.create();
                    event.one(key, fn, last);
                },
                remove: function (key, fn) {
                    var event = this.create();
                    event.remove(key, fn);
                },
                listen: function (key, fn, last) {
                    var event = this.create();
                    event.listen(key, fn, last);
                },
                trigger: function () {
                    var event = this.create();
                    event.trigger.apply(this, arguments);
                }
            }
        }()

        return Event;
    })();
觀察者(observer) 模式 和 發(fā)布/訂閱模式 之間的區(qū)別

本質(zhì)上的區(qū)別及時(shí)在調(diào)度的地方不同

分清楚誰是發(fā)布者, 誰是觀察者, 誰是訂閱者

觀察者模式

    // subject(發(fā)布) 中的目標(biāo)發(fā)生變化. Observer(觀察) 能接受到變化
    function ObserverList() {
        this.observerList = [];
    }

    ObserverList.prototype.add = function (obj) {
        return this.observerList.push(obj);
    }
    
    ObserverList.prototype.get = function (index) {
        if (index > -1 && this.observerList.length) {
            return this.observerList[index];
        }
    }

    ObserverList.prototype.indexOf = function (obj, startIndex) {
        var i = startIndex;

        while(i < this.observerList.length) {
            if (this.observerList[i] === obj) {
                return i;
            }
            i++;
        }

        return -1;
    }
    
    ObserverList.prototype.removeAt = function (index) {
        this.observerList.splice(index, 1);
    }
    
    // 發(fā)布者
    function Subject() {
        this.observers = new ObserverList();
    }

    Subject.prototype.addObserver = function (observer) {
        this.observers.add(observer);
    }

    Subject.prototype.removeObserver = function (observer) {
        this.observers.removeAt(this.observers.indexOf(observer, 0));
    }

    Subject.prototype.notify = function (context) {
        var observerCount = this.observers.count();
        for (var i = 0; i < observerCount; i++) {
            this.observers.get(i).update(context);
        }
    }

    // 觀察者
    function Observer() {
        this.update = function () {
            // ...
        }
    }

發(fā)布(Publish)/訂閱(Subscribe)模式

    var pubsub = {};
    (function (myObject) {
        var topics = {};

        var subUid = -1;

        // 發(fā)布
        myObject.publish = function (topic, args) {
            if (!topics[topic]) {
                return false;
            }

            var subscribers = topics[topic],
                len = subscribers ? subscribers.length : 0;

            while (len--) {
                subscribers[len].func(topic, args);
            }

            return this;
        }

        // 訂閱者
        myObject.subscribe = function (topic, func) {
            if (!topics[topic]) {
                topics[topic] = [];
            }

            var token = (++subUid).toString();

            topics[topic].push({
                token: token,
                func: func
            })
        }

        // 取消訂閱
        myObject.unsubscribe = function (token) {
            for (var m in topics) {
                if (topics[m]) {
                    for (var i = 0, j = topics[m].length; i < j; i++) {
                        if (topics[m][i].token === token) {
                            topics[m].splice(i, 1);
                            return token;
                        }
                    }
                }
            }
            return this;
        }
    })(pubsub)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/104533.html

相關(guān)文章

  • 前端學(xué)習(xí)筆記觀察者模式

    摘要:觀察者模式也稱發(fā)布訂閱模式它的作用就是當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對(duì)象都將得到通知,自動(dòng)刷新對(duì)象狀態(tài)舉個(gè)生活比較常見常見的例子比如你去面試之后,面試官看你表現(xiàn)不錯(cuò),最后會(huì)跟你要聯(lián)系方式,以便之后可以聯(lián)系你。 觀察者模式也稱發(fā)布-訂閱模式,它的作用就是當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),所有依賴于它的對(duì)象都將得到通知,自動(dòng)刷新對(duì)象狀態(tài) 舉個(gè)生活比較常見常見的例子,比如你去面試之后,...

    tommego 評(píng)論0 收藏0
  • JavaScript設(shè)計(jì)模式發(fā)布-訂閱模式(觀察者模式)-Part1

    摘要:設(shè)計(jì)模式與開發(fā)實(shí)踐讀書筆記。發(fā)布訂閱模式又叫觀察者模式,它定義了對(duì)象之間的一種一對(duì)多的依賴關(guān)系。附設(shè)計(jì)模式之發(fā)布訂閱模式觀察者模式數(shù)據(jù)結(jié)構(gòu)和算法系列棧隊(duì)列優(yōu)先隊(duì)列循環(huán)隊(duì)列設(shè)計(jì)模式系列設(shè)計(jì)模式之策略模式 《JavaScript設(shè)計(jì)模式與開發(fā)實(shí)踐》讀書筆記。 發(fā)布-訂閱模式又叫觀察者模式,它定義了對(duì)象之間的一種一對(duì)多的依賴關(guān)系。當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),所有依賴它的對(duì)象都將得到通知。 例...

    muzhuyu 評(píng)論0 收藏0
  • vue 雙向數(shù)據(jù)綁定的實(shí)現(xiàn)學(xué)習(xí)(一)

    摘要:雙向數(shù)據(jù)綁定簡(jiǎn)言之?dāng)?shù)據(jù)動(dòng)頁面動(dòng),頁面動(dòng),數(shù)據(jù)動(dòng)典型的應(yīng)用就是在做表單時(shí)候,輸入框的內(nèi)容改動(dòng)后,跟該輸入框的的值改動(dòng)。看官網(wǎng)上的這個(gè)的演示案例雙向數(shù)據(jù)綁定的好處要說出這個(gè)好處的時(shí)候,也只有在實(shí)際場(chǎng)景中才能對(duì)應(yīng)的顯示出來。 前言:本系列學(xué)習(xí)筆記從以下幾個(gè)點(diǎn)展開 什么是雙向數(shù)據(jù)綁定 雙向數(shù)據(jù)綁定的好處 怎么實(shí)現(xiàn)雙向數(shù)據(jù)綁定 實(shí)現(xiàn)雙向數(shù)據(jù)數(shù)據(jù)綁定需要哪些知識(shí)點(diǎn) 數(shù)據(jù)劫持 發(fā)布訂閱模式 ...

    anonymoussf 評(píng)論0 收藏0
  • JavaScript設(shè)計(jì)模式發(fā)布-訂閱模式(觀察者模式)-Part2

    摘要:設(shè)計(jì)模式與開發(fā)實(shí)踐讀書筆記。看此文章前,建議先看設(shè)計(jì)模式之發(fā)布訂閱模式觀察者模式在中,已經(jīng)介紹了什么是發(fā)布訂閱模式,同時(shí),也實(shí)現(xiàn)了發(fā)布訂閱模式。 《JavaScript設(shè)計(jì)模式與開發(fā)實(shí)踐》讀書筆記。 看此文章前,建議先看JavaScript設(shè)計(jì)模式之發(fā)布-訂閱模式(觀察者模式)-Part1 在Part1中,已經(jīng)介紹了什么是發(fā)布-訂閱模式,同時(shí),也實(shí)現(xiàn)了發(fā)布-訂閱模式。但是,就Part1...

    Charlie_Jade 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<