Javascript设计模式之中介者模式
前言:菜雞也有夢(mèng)想,而我的夢(mèng)想就是進(jìn)一個(gè)真正的互聯(lián)網(wǎng)大廠。以前學(xué)習(xí)的時(shí)候沒(méi)有系統(tǒng)的整理,從今天開(kāi)始要保持每周寫(xiě)博客的習(xí)慣,希望自己可以有所成長(zhǎng)。為了培養(yǎng)編程思維,決定從設(shè)計(jì)模式開(kāi)始寫(xiě)起。我是通過(guò)讀《Javascript設(shè)計(jì)模式與開(kāi)發(fā)實(shí)踐》來(lái)學(xué)習(xí)設(shè)計(jì)模式,并且將知識(shí)點(diǎn)和收獲記錄在博客中。
此文僅記錄本人閱讀《JavaScript設(shè)計(jì)模式與開(kāi)發(fā)實(shí)踐》的知識(shí)點(diǎn)與想法,感謝作者曾探大大寫(xiě)出這么好的一本書(shū)。如有冒犯,請(qǐng)聯(lián)系本人:markcoder@outlook.com處理,請(qǐng)大家購(gòu)買正版書(shū)籍。
1.中介者模式介紹
中介者模式的作用就是解除對(duì)象與對(duì)象之間的緊耦合關(guān)系。增加一個(gè)中介者對(duì)象后,所有的相關(guān)對(duì)象都通過(guò)中介者對(duì)象來(lái)通信,而不是互相引用,所以當(dāng)一個(gè)對(duì)象發(fā)生改變時(shí),只需要通知中介者對(duì)象即可。
改造后
2.代碼示例
這里還是使用書(shū)中的例子。
假設(shè)我們正在編寫(xiě)一個(gè)手機(jī)購(gòu)買的頁(yè)面,在購(gòu)買流程中,可以選擇手機(jī)的顏色以及輸入購(gòu)買數(shù)量,同時(shí)頁(yè)面中有兩個(gè)展示區(qū)域,分別向用戶展示剛剛選擇好的顏色和數(shù)量。還有一個(gè)按鈕動(dòng)態(tài)顯示下一步的操作,我們需要查詢?cè)擃伾謾C(jī)對(duì)應(yīng)的庫(kù)存,如果庫(kù)存數(shù)量少于這次的購(gòu)買數(shù)量,按鈕將被禁用并且顯示庫(kù)存不足,反之按鈕可以點(diǎn)擊并且顯示放入購(gòu)物車。
簡(jiǎn)單切一個(gè)頁(yè)面出來(lái)。
2.1 不使用中介者模式
接下來(lái)將分別監(jiān)聽(tīng) colorSelect 的 onchange 事件函數(shù)和 numberInput 的 oninput 事件函數(shù),然 后在這兩個(gè)事件中作出相應(yīng)處理。
let colorSelect = document.querySelector( '#colorSelect' ), numberInput = document.querySelector( '#numberInput' ), colorInfo = document.querySelector( '#colorInfo' ), numberInfo = document.querySelector( '#numberInfo' ), nextBtn = document.querySelector( '#nextBtn' );const goods = { // 模擬從接口取得手機(jī)庫(kù)存"red": 3, "blue": 6 };// 監(jiān)聽(tīng)顏色選擇器改變 colorSelect.addEventListener('change', () => {let color = colorSelect.value, // 顏色number = numberInput.value, // 數(shù)量stock = goods[ color ]; // 該顏色手機(jī)對(duì)應(yīng)的當(dāng)前庫(kù)存colorInfo.innerHTML = color;if ( !color ){ nextBtn.disabled = true; nextBtn.innerHTML = '請(qǐng)選擇手機(jī)顏色'; return; } if ( ( ( number - 0 ) | 0 ) !== number - 0 ){ // 用戶輸入的購(gòu)買數(shù)量是否為正整數(shù)nextBtn.disabled = true; nextBtn.innerHTML = '請(qǐng)輸入正確的購(gòu)買數(shù)量'; return; } if ( number > stock ){ // 當(dāng)前選擇數(shù)量沒(méi)有超過(guò)庫(kù)存量nextBtn.disabled = true; nextBtn.innerHTML = '庫(kù)存不足'; return; } nextBtn.disabled = false; nextBtn.innerHTML = '放入購(gòu)物車'; })// 監(jiān)聽(tīng)數(shù)量輸入框改變 numberInput.addEventListener('change', () => {let color = colorSelect.value, // 顏色number = numberInput.value, // 數(shù)量stock = goods[ color ]; // 該顏色手機(jī)對(duì)應(yīng)的當(dāng)前庫(kù)存numberInfo.innerHTML = number;if ( !color ){ nextBtn.disabled = true; nextBtn.innerHTML = '請(qǐng)選擇手機(jī)顏色'; return; } if ( ( ( number - 0 ) | 0 ) !== number - 0 ){ // 輸入購(gòu)買數(shù)量是否為正整數(shù)nextBtn.disabled = true; nextBtn.innerHTML = '請(qǐng)輸入正確的購(gòu)買數(shù)量'; return; }if ( number > stock ){ // 當(dāng)前選擇數(shù)量沒(méi)有超過(guò)庫(kù)存量nextBtn.disabled = true; nextBtn.innerHTML = '庫(kù)存不足'; return ; } nextBtn.disabled = false; nextBtn.innerHTML = '放入購(gòu)物車'; }) 復(fù)制代碼如果這時(shí)候,需求增加,又加入了CPU種類,那么又要擴(kuò)充CPU選擇框的函數(shù),如果刪除了某一種類的選擇,又要深入到每一個(gè)函數(shù)去修改,非常的麻煩,每個(gè)節(jié)點(diǎn)對(duì)象都是耦合在一起的,改變或者增加任何一個(gè)節(jié)點(diǎn)對(duì)象,都要通知到與其相關(guān)的對(duì)象。
2.2使用中介者模式改寫(xiě)
const goods = { // 模擬從接口取得手機(jī)庫(kù)存"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 // 數(shù)量if ( obj === colorSelect ){ // 如果改變的是選擇顏色下拉框colorInfo.innerHTML = color; }else if ( obj === numberInput ){ // 如果改變的是選擇顏色下拉框numberInfo.innerHTML = number; } if ( !color ){ nextBtn.disabled = true; nextBtn.innerHTML = '請(qǐng)選擇手機(jī)顏色'; return; } if ( ( ( number - 0 ) | 0 ) !== number - 0 ){ // 輸入購(gòu)買數(shù)量是否為正整數(shù)nextBtn.disabled = true; nextBtn.innerHTML = '請(qǐng)輸入正確的購(gòu)買數(shù)量'; return; } nextBtn.disabled = false; nextBtn.innerHTML = '放入購(gòu)物車'; }} })();// 事件函數(shù): colorSelect.addEventListener('change', () => {mediator.changed( colorSelect ); }); numberInput.addEventListener('input', () => {mediator.changed( numberInput ); }); 復(fù)制代碼可以想象,某天我們又要新增一些跟需求相關(guān)的節(jié)點(diǎn),比如內(nèi)存大小,那我們只需要稍稍改動(dòng) mediator 對(duì)象即可
新切一個(gè)頁(yè)面
const goods = { // 模擬從接口取得手機(jī)庫(kù)存"red": 3, "blue": 6 };const mediator = (() => {let colorSelect = document.querySelector( '#colorSelect' ), memorySelect = document.querySelector( '#memorySelect' ), // 新增內(nèi)存大小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, // 數(shù)量memory = memorySelect.valueif ( obj === colorSelect ){ // 如果改變的是選擇顏色下拉框colorInfo.innerHTML = color; } else if ( obj === numberInput ){ // 如果改變的是選擇顏色下拉框numberInfo.innerHTML = number; } else if ( obj === memorySelect ){ // 如果改變的是選擇內(nèi)存大小memoryInfo.innerHTML = memory; }if ( !color ){ nextBtn.disabled = true; nextBtn.innerHTML = '請(qǐng)選擇手機(jī)顏色'; return; } if ( !memory ){ // 新增內(nèi)存大小nextBtn.disabled = true; nextBtn.innerHTML = '請(qǐng)選擇手機(jī)內(nèi)存大小'; return; } if ( ( ( number - 0 ) | 0 ) !== number - 0 ){ // 輸入購(gòu)買數(shù)量是否為正整數(shù)nextBtn.disabled = true; nextBtn.innerHTML = '請(qǐng)輸入正確的購(gòu)買數(shù)量'; return; } nextBtn.disabled = false; nextBtn.innerHTML = '放入購(gòu)物車'; }} })();// 事件函數(shù):colorSelect.addEventListener('change', () => {mediator.changed( colorSelect ); }); memorySelect.addEventListener('change', () => {mediator.changed( memorySelect ); }); numberInput.addEventListener('input', () => { // 新增內(nèi)存大小mediator.changed( numberInput ); }); 復(fù)制代碼中介者模式可以非常方便地對(duì)模塊或者對(duì)象進(jìn)行解耦,但對(duì)象之間并非一定需要解耦。在實(shí) 際項(xiàng)目中,模塊或?qū)ο笾g有一些依賴關(guān)系是很正常的。畢竟我們寫(xiě)程序是為了快速完成項(xiàng)目交 付生產(chǎn),而不是堆砌模式和過(guò)度設(shè)計(jì)。關(guān)鍵就在于如何去衡量對(duì)象之間的耦合程度。一般來(lái)說(shuō), 如果對(duì)象之間的復(fù)雜耦合確實(shí)導(dǎo)致調(diào)用和維護(hù)出現(xiàn)了困難,而且這些耦合度隨項(xiàng)目的變化呈指數(shù) 增長(zhǎng)曲線,那我們就可以考慮用中介者模式來(lái)重構(gòu)代碼。
轉(zhuǎn)載于:https://juejin.im/post/5ce3b8fcf265da1b827a712e
總結(jié)
以上是生活随笔為你收集整理的Javascript设计模式之中介者模式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: React中的状态管理---Mobx
- 下一篇: win10下安装ubuntu,双系统,免