js之中介模式

購買商品

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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    選擇顏色: <select id="colorSelect">
        <option value="">請選擇</option>
        <option value="red">紅色</option>
        <option value="blue">藍色</option>
    </select><br/>
    輸入購買數量: <input type="text" id="numberInput"/><br/><br/>
    您選擇了顏色: <div id="colorInfo"></div><br/>
    您輸入了數量: <div id="numberInfo"></div><br/>
    <button id="nextBtn" disabled="true">請選擇手機顏色和購買數量</button>
    <script>
        var colorSelect = document.getElementById( 'colorSelect' ),
            numberInput = document.getElementById( 'numberInput' ),
            colorInfo = document.getElementById( 'colorInfo' ),
            numberInfo = document.getElementById( 'numberInfo' ),
            nextBtn = document.getElementById( 'nextBtn' );
        var goods = { // 手機庫存
            "red": 3,
            "blue": 6
        };
        colorSelect.onchange = function(){
            var color = this.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.oninput = function(){
            var color = colorSelect.value, // 顏色
                number = this.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 = '放入購物車';
};
</script>
</body>
</html>

運用中介模式

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    選擇顏色: <select id="colorSelect">
        <option value="">請選擇</option>
        <option value="red">紅色</option>
        <option value="blue">藍色</option>
    </select>
    選擇內存: <select id="memorySelect">
        <option value="">請選擇</option>
        <option value="32G">32G</option>
        <option value="16G">16G</option>
    </select>
    輸入購買數量: <input type="text" id="numberInput"/><br/>
    您選擇了顏色: <div id="colorInfo"></div><br/>
    您選擇了內存: <div id="memoryInfo"></div><br/>
    您輸入了數量: <div id="numberInfo"></div><br/>
    <button id="nextBtn" disabled="true">請選擇手機顏色和購買數量</button>
    <script>
        var goods = { // 手機庫存
            "red|32G": 3,
            "red|16G": 0,
            "blue|32G": 1,
            "blue|16G": 6
        };
        var mediator = (function(){
            var colorSelect = document.getElementById( 'colorSelect' ),
                memorySelect = document.getElementById( 'memorySelect' ),
                numberInput = document.getElementById( 'numberInput' ),
                colorInfo = document.getElementById( 'colorInfo' ),
                memoryInfo = document.getElementById( 'memoryInfo' ),
                numberInfo = document.getElementById( 'numberInfo' ),
                nextBtn = document.getElementById( 'nextBtn' );
            return {
                changed: function( obj ){
                    var color = colorSelect.value, // 顏色
                        memory = memorySelect.value,// 內存
                        number = numberInput.value, // 數量
                        stock = goods[ color + '|' + memory ]; // 顏色和內存對應的手機庫存數量
                    if ( obj === colorSelect ){ // 如果改變的是選擇顏色下拉框
                        colorInfo.innerHTML = color;
                    }else if ( obj === memorySelect ){
                        memoryInfo.innerHTML = memory;
                    }else if ( obj === numberInput ){
                        numberInfo.innerHTML = number;
                    }
                    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.onchange = function(){
            mediator.changed( this );
        };
        memorySelect.onchange = function(){
            mediator.changed( this );
        };
        numberInput.oninput = function(){
            mediator.changed( this );
        };
    </script>
</body>
</html>

小結

中介者模式是迎合迪米特法則的一種實現。迪米特法則也叫最少知識原則,是指一個對象應該儘可能少地瞭解另外的對象(類似不和陌生人說話)。如果對象之間的耦合性太高,一個對象發生改變之後,難免會影響到其他的對象,跟“城門失火,殃及池魚”的道理是一樣的。而在中介者模式裏,對象之間幾乎不知道彼此的存在,它們只能通過中介者對象來互相影響對方。

因此,中介者模式使各個對象之間得以解耦,以中介者和對象之間的一對多關係取代了對象之間的網狀多對多關係。各個對象只需關注自身功能的實現,對象之間的交互關係交給了中介者對象來實現和維護。

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章