Javascript設計模式之中介者模式

前言:菜雞也有夢想,而個人夢想就是進一個真正的互聯網大廠。之前學習的時候沒有系統的整理,從今天開始要保持每週寫博客的習慣,但願本身能夠有所成長。爲了培養編程思惟,決定從設計模式開始寫起。我是經過讀《Javascript設計模式與開發實踐》來學習設計模式,而且將知識點和收穫記錄在博客中。編程

此文僅記錄本人閱讀《JavaScript設計模式與開發實踐》的知識點與想法,感謝做者曾探大大寫出這麼好的一本書。若有冒犯,請聯繫本人:markcoder@outlook.com處理,請你們購買正版書籍。設計模式

1.中介者模式介紹

中介者模式的做用就是解除對象與對象之間的緊耦合關係。增長一箇中介者對象後,全部的相關對象都經過中介者對象來通訊,而不是互相引用,因此當一個對象發生改變時,只須要通知中介者對象便可。bash

改造後函數

2.代碼示例

這裏仍是使用書中的例子。學習

假設咱們正在編寫一個手機購買的頁面,在購買流程中,能夠選擇手機的顏色以及輸入購買數量,同時頁面中有兩個展現區域,分別向用戶展現剛剛選擇好的顏色和數量。還有一個按鈕動態顯示下一步的操做,咱們須要查詢該顏色手機對應的庫存,若是庫存數量少於此次的購買數量,按鈕將被禁用而且顯示庫存不足,反之按鈕能夠點擊而且顯示放入購物車。ui

簡單切一個頁面出來。spa

2.1 不使用中介者模式

接下來將分別監聽 colorSelect 的 onchange 事件函數和 numberInput 的 oninput 事件函數,然 後在這兩個事件中做出相應處理。設計

let colorSelect = document.querySelector( '#colorSelect' ), 
            numberInput = document.querySelector( '#numberInput' ), 
            colorInfo = document.querySelector( '#colorInfo' ), 
            numberInfo = document.querySelector( '#numberInfo' ), 
            nextBtn = document.querySelector( '#nextBtn' );

const goods = { // 模擬從接口取得手機庫存
    "red": 3, 
    "blue": 6 
};

// 監聽顏色選擇器改變
colorSelect.addEventListener('change', () => {
    let color = colorSelect.value, // 顏色
    number = numberInput.value, // 數量
    stock = goods[ color ]; // 該顏色手機對應的當前庫存
    colorInfo.innerHTML = color;

    if ( !color ){ 
        nextBtn.disabled = true; 
        nextBtn.innerHTML = '請選擇手機顏色'; 
        return; 
    } 
    if ( ( ( number - 0 ) | 0 ) !== number - 0 ){ // 用戶輸入的購買數量是否爲正整數
        nextBtn.disabled = true; 
        nextBtn.innerHTML = '請輸入正確的購買數量'; 
        return; 
    } 
    if ( number > stock ){ // 當前選擇數量沒有超過庫存量
        nextBtn.disabled = true; 
        nextBtn.innerHTML = '庫存不足'; 
        return; 
    } 
    nextBtn.disabled = false; 
    nextBtn.innerHTML = '放入購物車';
})

// 監聽數量輸入框改變
numberInput.addEventListener('change', () => {
    let color = colorSelect.value, // 顏色
        number = numberInput.value, // 數量
        stock = goods[ color ]; // 該顏色手機對應的當前庫存
    numberInfo.innerHTML = number;

    if ( !color ){ 
        nextBtn.disabled = true; 
        nextBtn.innerHTML = '請選擇手機顏色'; 
        return; 
    } 
    if ( ( ( number - 0 ) | 0 ) !== number - 0 ){ // 輸入購買數量是否爲正整數
        nextBtn.disabled = true; 
        nextBtn.innerHTML = '請輸入正確的購買數量'; 
        return; 
    }
    if ( number > stock ){ // 當前選擇數量沒有超過庫存量
        nextBtn.disabled = true; 
        nextBtn.innerHTML = '庫存不足'; 
        return ; 
    } 
    nextBtn.disabled = false; 
    nextBtn.innerHTML = '放入購物車';
})
複製代碼

若是這時候,需求增長,又加入了CPU種類,那麼又要擴充CPU選擇框的函數,若是刪除了某一種類的選擇,又要深刻到每個函數去修改,很是的麻煩,每一個節點對象都是耦合在一塊兒的,改變或者增長任何一個節點對象,都要通知到與其相關的對象。3d

2.2使用中介者模式改寫

const goods = { // 模擬從接口取得手機庫存
    "red": 3, 
    "blue": 6 
};

const mediator = (() => {
    let colorSelect = document.querySelector( '#colorSelect' ), 
    numberInput = document.querySelector( '#numberInput' ), 
    colorInfo = document.querySelector( '#colorInfo' ), 
    numberInfo = document.querySelector( '#numberInfo' ), 
    nextBtn = document.querySelector( '#nextBtn' );

    return {
        changed: function( obj ){ 
            let color = colorSelect.value, // 顏色
                number = numberInput.value // 數量
            if ( obj === colorSelect ){ // 若是改變的是選擇顏色下拉框
                colorInfo.innerHTML = color; 
            }else if ( obj === numberInput ){ // 若是改變的是選擇顏色下拉框
                numberInfo.innerHTML = number; 
            } 
            if ( !color ){ 
                nextBtn.disabled = true; 
                nextBtn.innerHTML = '請選擇手機顏色'; 
                return; 
            } 
            if ( ( ( number - 0 ) | 0 ) !== number - 0 ){ // 輸入購買數量是否爲正整數
                nextBtn.disabled = true; 
                nextBtn.innerHTML = '請輸入正確的購買數量'; 
                return; 
            } 
            nextBtn.disabled = false; 
            nextBtn.innerHTML = '放入購物車'; 
        }
    }
})();

// 事件函數:
colorSelect.addEventListener('change', () => {
    mediator.changed( colorSelect ); 
}); 
numberInput.addEventListener('input', () => {
    mediator.changed( numberInput ); 
}); 
複製代碼

能夠想象,某天咱們又要新增一些跟需求相關的節點,好比內存大小,那咱們只須要稍稍改動 mediator 對象便可code

新切一個頁面

const goods = { // 模擬從接口取得手機庫存
    "red": 3, 
    "blue": 6 
};

const mediator = (() => {
    let colorSelect = document.querySelector( '#colorSelect' ), 
    memorySelect = document.querySelector( '#memorySelect' ), // 新增內存大小
    numberInput = document.querySelector( '#numberInput' ), 
    colorInfo = document.querySelector( '#colorInfo' ), 
    numberInfo = document.querySelector( '#numberInfo' ), 
    nextBtn = document.querySelector( '#nextBtn' );
    return {
        changed: function( obj ){ 
            let color = colorSelect.value, // 顏色
                number = numberInput.value, // 數量
                memory = memorySelect.value
            if ( obj === colorSelect ){ // 若是改變的是選擇顏色下拉框
                colorInfo.innerHTML = color; 
            } else if ( obj === numberInput ){ // 若是改變的是選擇顏色下拉框
                numberInfo.innerHTML = number; 
            } else if ( obj === memorySelect ){ // 若是改變的是選擇內存大小
                memoryInfo.innerHTML = memory; 
            }
            if ( !color ){ 
                nextBtn.disabled = true; 
                nextBtn.innerHTML = '請選擇手機顏色'; 
                return; 
            } 
            if ( !memory ){  // 新增內存大小
                nextBtn.disabled = true;  
                nextBtn.innerHTML = '請選擇手機內存大小'; 
                return; 
            } 
            if ( ( ( number - 0 ) | 0 ) !== number - 0 ){ // 輸入購買數量是否爲正整數
                nextBtn.disabled = true; 
                nextBtn.innerHTML = '請輸入正確的購買數量'; 
                return; 
            } 
            nextBtn.disabled = false; 
            nextBtn.innerHTML = '放入購物車'; 
        }
    }
})();

// 事件函數:

colorSelect.addEventListener('change', () => {
    mediator.changed( colorSelect ); 
}); 
memorySelect.addEventListener('change', () => {
    mediator.changed( memorySelect ); 
}); 
numberInput.addEventListener('input', () => { // 新增內存大小
    mediator.changed( numberInput ); 
}); 
複製代碼

中介者模式能夠很是方便地對模塊或者對象進行解耦,但對象之間並不是必定須要解耦。在實 際項目中,模塊或對象之間有一些依賴關係是很正常的。畢竟咱們寫程序是爲了快速完成項目交 付生產,而不是堆砌模式和過分設計。關鍵就在於如何去衡量對象之間的耦合程度。通常來講, 若是對象之間的複雜耦合確實致使調用和維護出現了困難,並且這些耦合度隨項目的變化呈指數 增加曲線,那咱們就能夠考慮用中介者模式來重構代碼。

相關文章
相關標籤/搜索