摘要:好,師傅我們要學(xué)習(xí)帝吧人民,進(jìn)能打,退能刷淘寶。恩,大致過程就是這樣,我們使用中介者模式想一想。首先,數(shù)據(jù)需要放在中介者模式內(nèi),用戶的一切操作,都會傳遞給中介者模式,由他來選擇是哪一個(gè)部分發(fā)生改變。
俗話說,一個(gè)模式三個(gè)坑。 中介者模式應(yīng)該算最坑的一個(gè)模式,坑不在于他的原理。而在于他的名字和其他模式的使用,真尼瑪像。首先,“中介者“ 好像是一切模式里面都有的一個(gè)東西,比如,享元模式中-元對象,訂閱發(fā)布模式中-全局監(jiān)聽Event... 但是,這個(gè)模式偏偏又叫做中介者模式(哎,曾經(jīng)說模式的時(shí)候,感覺什么都是中介者模式)。
所以,這里我們首先要攻克的難關(guān)就是,中介者模式的features。
中介者模式首先,我們需要回憶一下使用訂閱發(fā)布模式中,是怎樣一個(gè)場景
恩,中間需要有一個(gè)連接節(jié)點(diǎn),即,發(fā)布者只需要和連接者有關(guān)聯(lián),而訂閱者同樣也只需要和連接者有關(guān)聯(lián)。 所以,這個(gè)點(diǎn)就是中介者模式最獨(dú)特的feature. 下圖可以清楚的看出,中介者模式的特點(diǎn)。
知道了吧,中介者模式最突出的就是,由中介者來掌管一切,比訂閱者中的連接節(jié)點(diǎn)的地位好像就是爸爸和兒子的關(guān)系。
中介者模式的實(shí)現(xiàn)在發(fā)布訂閱模式中有著全局對象Event的管理,那中介者模式中的boss應(yīng)該怎樣表達(dá)呢?
首先,我們需要說明一下,中介者模式主要的應(yīng)用場景是什么。
有大量相互關(guān)聯(lián)的對象
每個(gè)對象都能改變狀態(tài)
你寫的代碼比較爛
差不多中介者模式能夠解決以上的問題。
徒兒,給師傅去要個(gè)栗子來。
好的,師傅?。?!
栗子來了:
大家好,(我假裝我是一名學(xué)霸) 同學(xué)們可能經(jīng)常去的地方,應(yīng)該就是圖書館了,經(jīng)常會去圖書管理處借一些書來看,比如: 藏地密碼,阿彌陀佛么么噠...等等。我們憑借著盡職的圖書館阿姨,往往可以借到我們想要的書本。如果已經(jīng)被借走了,還可以在阿姨那里登記,并且如果書還回來的,會通知你過來取。
恩,總結(jié)一下:
圖書館阿姨其實(shí)就是一個(gè)中介者,我們找書,都是通過圖書管理處詢問,然后他們負(fù)責(zé)給我們查詢。 如果沒有這個(gè)管理處的話,就像我們平時(shí)一樣,在群里問問,"大家有xxx書嗎?能借我看兩天嗎?"。當(dāng)然,這樣往往會石沉大海。
我們用代碼模擬一下:
//我們先假設(shè)圖書管理系統(tǒng)只有借和還的功能 //個(gè)人 function Person(name){ this.name = name; } Person.prototype.lend = function(bookName){ Manager.assign("lend",this,bookName); } Person.prototype.back = function(bookName){ Manager.assign("back",this,bookName); } //創(chuàng)建一個(gè)工廠模式 var peopleFactory = (function(){ var people = {}; return function(name){ var person = people[name]; if(person){ return person; } person = new Person(name); people[name] = person; return person; } })(); //中介者,圖書管理處 var Manager = (function(){ var lendList = {}, stock = {}, operations = {}; operations.lend = function(person,bookName){ var num = stock[bookName]; if(num===undefined){ //判斷是否有書 console.log("圖書館沒有該書"); return; } if(num===0){ //書本已經(jīng)借完 console.log("該書已經(jīng)借完"); return; } stock[bookName]--; //將數(shù)量減一 lendList[person.name] = bookName; console.log("借閱成功"); } operations.back = function(person,bookName){ var bookName = lendList[person.name]; //返回借書人借的書名 if(bookName === null){ throw "該人,并沒有借書"; } stock[bookName]++; //還書 lendList[person.name] = null; //將借書人的清空 } operations.addStock = function(){ //初始庫存,addStock({bookName:jimmy,num:2}) for(var i = 0,book;book = arguments[i++];){ stock[book.bookName] = book.num; } } var assign = function(){ var order = Array.prototype.shift.call(arguments); operations[order].apply(this,arguments); } return { assign } })(); Manager.assign("addStock",{bookName:"藏地密碼",num:1},{bookName:"阿彌陀佛么么噠",num:3}); var xiaoMing = peopleFactory("xiaoMing"); var jimmy = peopleFactory("jimmy"); var hanMM = peopleFactory("hanMM"); xiaoMing.lend("藏地密碼"); jimmy.lend("藏地密碼"); //還書的過程 xiaoMing.back("藏地秘密"); jimmy.lend("藏地密碼"); //終于借成功了
以上是一個(gè)簡單的中介者模式的縮影,要始終記著那張圖代表的內(nèi)涵,中介者模式是不需要在將請求傳遞出去的(或者說,情感上沒有傳遞出去)。
中介者模式的現(xiàn)實(shí)意義上面意淫了一個(gè)圖書管理處(實(shí)話說,沒有卵用). 我們來個(gè)真的。
徒兒,給師傅找個(gè)栗子。
好,師傅!!!
我們要學(xué)習(xí)帝吧人民,進(jìn)能打td,退能刷淘寶。 我們這里不說淘寶的事,但說一個(gè)電子商務(wù)的事。 現(xiàn)在Mooc這么火,各種線上課程也是numberous。我也上過。 一個(gè)線上的課程需要購買,購買的流程基本上就是,選擇你想要的課程,然后,選擇你要上課的人數(shù)(你是一個(gè)媽媽,你可以給你兩個(gè)孩紙各買一個(gè)ID),如果上課人數(shù)未滿的話,恭喜,你在家等開課就over了。如果課程滿的話,你要么等下一期,要么,直接找另外一門課。
如果使用,面向過程的思維寫的話,我相信這個(gè),不是一般的復(fù)雜。
所以,我們使用面向?qū)ο蟮乃季S重構(gòu)一下。
首先,我們得拿到課程的數(shù)據(jù),比如,課程名,已經(jīng)報(bào)的課程人數(shù),課程價(jià)格等。當(dāng)我們選擇一個(gè)課程的時(shí)候,界面上肯定需要作出相應(yīng)的處理,比如,渲染課程價(jià)格,剩余人數(shù)。但我們添加購買人數(shù)的時(shí)候,如果未超出,則可以購買,如果超出,則需要將購買的按鈕改為不可選中狀態(tài)。
恩,大致過程就是這樣,我們使用中介者模式想一想。
首先,數(shù)據(jù)需要放在中介者模式內(nèi),用戶的一切操作,都會傳遞給中介者模式,由他來選擇是哪一個(gè)html部分發(fā)生改變。
好,我們用代碼實(shí)現(xiàn)以下。
課程購買
上面是整個(gè)邏輯和頁面,這里我主要針對js說明一下。
(function() { console.dir($(".courses")) bind($(".courses"), function(e) { //課程內(nèi)容改變時(shí) mediator.command(e.target); }, "change"); bind($(".num"), function(e) { //報(bào)名人數(shù)改變時(shí) mediator.command(e.target); }, "keyup"); bind($(".buy"), function(e) { //綁定夠買函數(shù) mediator.command(e.target); }, "click"); var utils = (function() { //工具函數(shù) var change = function(ele, val) { //改變內(nèi)容 ele.innerHTML = val; } return { change }; })(); var mediator = (function() { //中介者 var price = $(".price"), //課程價(jià)格 remainder = $(".remainder"), //剩余人數(shù) num = $(".num"), //購買人數(shù) buyBtn = $(".buy"), //購買btn course; var changePR = function(courseName) { //改變價(jià)格和人數(shù) course = data[courseName]; console.log(course); utils.change(price, course.price); //改變價(jià)格 utils.change(remainder, course.remainder); //改變?nèi)藬?shù) } var prohitBtn = (function() { //改變購買btn狀態(tài) var use = ``, ban = ``, status = true; return function(flag) { if (status === flag) { //如果狀態(tài)不變,則不改變內(nèi)容 return; } if (flag === true) { //可以購買 buyBtn.innerHTML = use; status = true; } else { //禁止購買 buyBtn.innerHTML = ban; status = false; } } })(); var detect = function() { //檢測購買輸入的內(nèi)容 var number = Number(num.value.trim()); if (!course) { alert("請先選擇課程"); return; } if (number > course.remainder) { prohitBtn(false); //不能夠買 } else { prohitBtn(true); //可以夠買 } } //當(dāng)課程類改變時(shí),觸發(fā)改變名額,價(jià)格以及根據(jù)購買人數(shù)改變購買Btn的狀態(tài) var coursesChange = function(courseName) { //改變價(jià)格和人數(shù) changePR(courseName); //根據(jù)input框的值,改變btn的狀態(tài) detect(); } var detectBuy = function() { var number = Number(num.value.trim()); if (number === null || number == 0) { alert("請先輸入購買數(shù)量~"); } else { alert("購買成功"); } } var command = function(target) { var classList = target.classList; if (classList.contains("courses")) { console.dir(target.value); var val = target.value; //執(zhí)行 coursesChange(val); } else if (classList.contains("num")) { var val =target.value.trim(), reg = /d+/; if (!reg.test(val)) { alert("輸入內(nèi)容只能為數(shù)字"); return; } //執(zhí)行 detect(); } else if(classList.contains("shoppingBtn")){ detectBuy(); } } return { command } })(); })();
可以從上面的代碼看出,比較清晰的將溝壑關(guān)系解除,上面的中介者模式中也會用到代理模式等其他相關(guān)的知識。當(dāng)然,這段代碼并不是特別好,關(guān)鍵在于處理的邏輯較多,有大量的if判斷語句,所以也希望讀者,可以使用以前所學(xué)的js模式進(jìn)行重構(gòu),我相信到時(shí)候你的代碼整潔程度一定遠(yuǎn)優(yōu)于鄙人寫的代碼。
淺說中介者模式其實(shí),中介者模式是我最喜歡使用的模式之一,因?yàn)樗脤懸咨鲜帧5侨秉c(diǎn)也是顯而易見的,就是,你會在程序中增加一個(gè)巨大的對象,而你的噩夢就是維護(hù)這個(gè)對象。 中介者里面會包含大量的邏輯,設(shè)計(jì)較多的節(jié)點(diǎn)獲取,造成的維護(hù)難度也是顯而易見的。所以,還是那句話,不要為了模式而模式,這個(gè)世界上沒有萬能的模式,就和沒有絕對安全的系統(tǒng)一樣。
ending~
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/78527.html
摘要:前端日報(bào)精選在中的元素種類及性能優(yōu)化譯異步遞歸回調(diào)譯定位一個(gè)頁面阻塞問題的排查過程前端分享之的使用及單點(diǎn)登錄中文視頻如何用做好一個(gè)大型應(yīng)用云際個(gè)實(shí)用技巧眾成翻譯年一定不要錯(cuò)過的五本編程書籍年前端領(lǐng)域有哪些探索和實(shí)踐實(shí)現(xiàn)一個(gè)時(shí)光網(wǎng)掘金 2017-09-22 前端日報(bào) 精選 JavaScript 在 V8 中的元素種類及性能優(yōu)化【譯】異步遞歸:回調(diào)、Promise、Async[譯]HTML...
摘要:用中介者模式實(shí)現(xiàn)土豆饅頭豆包地瓜土豆饅頭豆包地瓜土豆饅頭輸出缺陷使用中介者模式可以很大程度上避免對象之間的相互影響,無論是對于代碼的可讀性以及邏輯性都可以簡化。 中介者模式 我們知道在程序中各個(gè)對象之間并不是完全獨(dú)立的,相互之間是可能存在關(guān)系的,并且可能會相互影響的,就像這樣。 showImg(https://segmentfault.com/img/bVJ8wK?w=428&h=51...
摘要:抽象工廠模式是為了處理對象具有等級結(jié)構(gòu)以及對象族的問題。單例設(shè)計(jì)模式單例模式確保某一個(gè)類只有一個(gè)實(shí)例,而且自行實(shí)例化并向整個(gè)系統(tǒng)提供這個(gè)實(shí)例,這個(gè)類成為單例類。 導(dǎo)語:設(shè)計(jì)模式是無數(shù)碼農(nóng)前人在實(shí)際的生產(chǎn)項(xiàng)目中經(jīng)過不斷的踩坑、爬坑、修坑的經(jīng)歷總結(jié)出來的經(jīng)驗(yàn)教訓(xùn),經(jīng)過抽象之后表達(dá)成的概念。能夠幫助后來的設(shè)計(jì)者避免重復(fù)同樣的錯(cuò)誤或者彎路。我也抽空整理了一下設(shè)計(jì)模式,用自己的話總結(jié)了一下,自認(rèn)...
摘要:中介者模式中介者模式對象和對象之間借助第三方中介者進(jìn)行通信。將就用下這個(gè)這個(gè)函數(shù)充當(dāng)中介者挑戰(zhàn)成功挑戰(zhàn)失敗選手選手選手選手挑戰(zhàn)成功選手挑戰(zhàn)成功選手挑戰(zhàn)失敗在這段代碼中之間沒有直接發(fā)生關(guān)系而是通過另外的對象建立鏈接姑且將之當(dāng)成是中介者模式了。 中介者模式 中介者模式: 對象和對象之間借助第三方中介者進(jìn)行通信。 showImg(https://segmentfault.com/img/bV...
摘要:中介者模式的應(yīng)用中介者模式的優(yōu)點(diǎn)就是減少類間的依賴,將一對多的依賴變成一對一的依賴,降低耦合,符合迪米特法則。中介者模式適用于多個(gè)對象之間出現(xiàn)緊密聯(lián)系,類圖成網(wǎng)狀結(jié)構(gòu),使用中介者模式可以梳理為星型結(jié)構(gòu),有助于理解其關(guān)系。 前言 由于最近瘋狂加班,博客都停更許久,難過~.~ 中介者模式定義 用一個(gè)中介對象封裝一系列的對象交互,中介者使各對象不需要顯示地相互作用,從而使其耦合松散,而且可以...
閱讀 1833·2021-11-18 13:21
閱讀 1966·2021-10-18 13:30
閱讀 1551·2021-10-12 10:13
閱讀 922·2021-10-09 09:43
閱讀 5436·2021-09-22 15:13
閱讀 3595·2021-08-11 10:22
閱讀 947·2019-08-30 13:46
閱讀 3527·2019-08-30 13:21