前言:菜雞也有夢想,而個人夢想就是進一個真正的互聯網大廠。之前學習的時候沒有系統的整理,從今天開始要保持每週寫博客的習慣,但願本身能夠有所成長。爲了培養編程思惟,決定從設計模式開始寫起。我是經過讀《Javascript設計模式與開發實踐》來學習設計模式,而且將知識點和收穫記錄在博客中。編程
此文僅記錄本人閱讀《JavaScript設計模式與開發實踐》的知識點與想法,感謝做者曾探大大寫出這麼好的一本書。若有冒犯,請聯繫本人:markcoder@outlook.com處理,請你們購買正版書籍。設計模式
中介者模式的做用就是解除對象與對象之間的緊耦合關係。增長一箇中介者對象後,全部的相關對象都經過中介者對象來通訊,而不是互相引用,因此當一個對象發生改變時,只須要通知中介者對象便可。bash
改造後函數
這裏仍是使用書中的例子。學習
假設咱們正在編寫一個手機購買的頁面,在購買流程中,能夠選擇手機的顏色以及輸入購買數量,同時頁面中有兩個展現區域,分別向用戶展現剛剛選擇好的顏色和數量。還有一個按鈕動態顯示下一步的操做,咱們須要查詢該顏色手機對應的庫存,若是庫存數量少於此次的購買數量,按鈕將被禁用而且顯示庫存不足,反之按鈕能夠點擊而且顯示放入購物車。ui
簡單切一個頁面出來。spa
接下來將分別監聽 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
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 );
});
複製代碼
中介者模式能夠很是方便地對模塊或者對象進行解耦,但對象之間並不是必定須要解耦。在實 際項目中,模塊或對象之間有一些依賴關係是很正常的。畢竟咱們寫程序是爲了快速完成項目交 付生產,而不是堆砌模式和過分設計。關鍵就在於如何去衡量對象之間的耦合程度。通常來講, 若是對象之間的複雜耦合確實致使調用和維護出現了困難,並且這些耦合度隨項目的變化呈指數 增加曲線,那咱們就能夠考慮用中介者模式來重構代碼。