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