1. 程式人生 > 程式設計 >怎樣用JavaScript實現觀察者模式

怎樣用JavaScript實現觀察者模式

概述

觀察者模式又被稱為釋出-訂閱模式,是設計模式中的一種行為型模式;

定義:

觀察者模式定義了一種一對多的物件依賴關係,當被依賴的物件的狀態發生了改變,所有依賴它的物件都會得到通知;

白話解釋:

假如你去蘋果專賣店買最新款的iphone11,因為iphone11剛出來不久,正處旺季,供貨不足;當你去專賣店的時候,店員告訴你暫時沒貨了,但是你可以留下你的聯絡方式,如果貨到了,會第一時間通知;當然你肯定不會每天都去專賣店問iphone11到貨沒有,也不會天天給專賣店打電話,因為你有你自己的工作和生活,不可能有那麼多閒暇時間;所以此時,店員讓你留下聯絡方式,到貨了第一時間通知你,不會給你帶來麻煩,而你只需要等著專賣店的電話即可;而這種方法就是一種典型的觀察者模式;

首先我們還是來分析一下:

1.訂閱方法:我們把聯絡方式給專賣店店員是屬於一種訊息訂閱的訊息,因為只有這樣你才能及時的知道iphone11到貨了,所有我們需要一個訂閱行為的具體方法;

2.預訂列表:要知道iphonwww.cppcns.come11是屬於新版iphone,所以肯定不會是隻有你一個人去預訂,所以店員為了方便統計還需要一個預訂列表來統計所有的預訂者的聯絡方式以及預訂手機版本資訊,所以我們這裡先給它定義程式設計客棧為一個物件;key代表是預訂者的聯絡方式,value代表預訂手機版本資訊;

3.釋出方法:當iphone11到貨的時候,專賣店肯定要根據預訂列表來進行統一發布訊息("iphone11到貨了,大家快來搶!!!"),所以專賣店需要一個釋出方法來實行具體的釋出行為;、

4.取消訂閱:萬物相對,能訂閱肯定就能程式設計客棧取消訂閱;在等待iphone11到貨通知的時候,你急著用手機,所以直接買了華為的某款,所以iphone11暫時對你來說需求不大,因為你已經有了手機所以專賣店的iphone11是否到貨對你來說沒有任何意義了;所以此時你不想被打擾,需要取消訂閱訊息;所以我們需要一個取消訂閱方法來實現具體的取消訂閱的行為;

觀察者模式的應用場景

1、DOM事件

如果你是一個前端開發人員,不管你讀這篇文章之前是否已經瞭解觀察者模式,但是我能肯定你已經用過觀察者模式程式設計客棧

document.body.addEventListener('click',function() {
    console.log('hello world!');
});

這段程式碼看著眼熟嗎?是的,這是一個DOM事件的監聽;我們通過給body訂閱click事件(click相當於上面的訂閱方法),因為瀏覽器並不知道你什麼時候點選滑鼠,所以等你觸發click事件的時候才會觸發函式給你釋出通知(釋出方法);DOM事件就是一個觀察者模式的實現;

2、vue雙向繫結v-model

我們作為前端開發人員,肯定知道vue是一個MVVM模式的框架;vue的核心就是雙向繫結,那麼雙向繫結的實現實際上就是一種觀察者模式;因為你首先綁定了一個數據之後(訂閱方法),瀏覽器並不知道你什麼時候修改,你頁面上所有綁定了該資料或者依賴該資料的節點其實就是一個預訂列表,只有等你修改了該資料的值的時候,vue才會通知(釋出方法)到依賴該資料的方法/資料進行相應的操作或重新整理;

當然觀察者模式絕不僅限於這倆種實現場景,在我們的生活中、業務場景中有很多觀察者模式的示例,之前我們第一篇工廠模式介紹設計模式的時候就說過了,設計模式是一種解決問題的思路而非一種固定的公式,那麼我們怎麼實現觀察者模式呢?

觀察者模式的實現

//定義商家
var merchants = {};
//定義預訂列表
merchants.orderList = {};
//將增加的預定者新增到預訂列表中   (訂閱方法)
merchants.listen = function(id,info){
    //如果存在
    if(!this.orderList[id]){
        // (預訂列表)
        this.orderList[id] = [];
    }
    // 將使用者的預定的產品資訊存入到陣列中
    this.orderList[id].push(info);
}
//釋出資訊(釋出方法)
merchants.publish = function(){
    var id = Array.prototype.shift.call(arguments);
    var infos = this.orderList[id];
    if(!infos || infos.length === 0){
        console.log("您還沒有預定資訊");
        return false;
    }

    for(var i = 0;i < infos.length;i++){
        console.log("預定成功");
        console.log("尊敬的使用者:")
        infos[i].apply(this,arguments);
        console.log("到貨了");
    }
}
//取消訂閱  
merchants.remove = function(id,fn){
    var infos = this.orderList[id];
    if(!infos){ return false}

    if(!fn){
        console.log(123);
    }else{
        for(var i = 0;i < infos.length;i++){
            if(infos[i] === fn){
                infos.splice(i,1);
            }
        }
    }
}
let customeA = function(){
    console.log("黑色尊享版一臺");
}

merchants.listen("15172103336",customeA);
merchants.remove("15172103336",customeA);
merchants.publish("15172103336");

上面的程式碼稍微有點長,不過沒有很難;首先我們是定義了一個物件是作為商家,然後定義了一個空的物件作為預訂列表,再一步步的實現我們的訂閱方法和釋出以及取消訂閱的方法;邏輯不復雜,但是有一些語法需要講解一下:

釋出方法中的var id = Array.prototype.shift.call(arguments);這句的意思是將merchants.publish("15172103336");方法呼叫的時候第一個引數返回給它然後複製為id,所以其實此時的id值為”15172103336“;

infos[i].apply(this,arguments);這個方法也不是特別好理解,首先infos裡裝的是預訂者的手機號碼以及手機版本資訊,所以我們infos[i].apply(this,arguments);這個方法其實就是將"15172103336"對應的手機版本資訊函式進行呼叫了一遍;實際上等於i程式設計客棧nfos[i](arguments);

總結

觀察者模式不管是在前端領域還是在現實生活中的應用都是有很常見的場景,學好觀察者模式有利用我們學習vue的原始碼知識,當然不僅限於此,所以觀察者模式值得我們好好學習,一句話:"你品,你細品!" 今天付出的努力,在日後總會換成工資來回報你的!

以上就是怎樣用javascript實現觀察者模式的詳細內容,更多關於javaScript觀察者模式的資料請關注我們其它相關文章!