您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關javascript設計模式之中介者模式的示例分析,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
Java主要應用于:1. web開發;2. Android開發;3. 客戶端開發;4. 網頁開發;5. 企業級應用開發;6. Java大數據開發;7.游戲開發等。
先來理解這么一個問題,假如我們前端開發接的需求是需求方給我們需求,可能一個前端開發會和多個需求方打交道,所以會保持多個需求方的聯系,那么在程序里面就意味著保持多個對象的引用,當程序的規模越大,對象會越來越多,他們之間的關系會越來越復雜,那現在假如現在有一個中介者(假如就是我們的主管)來對接多個需求方的需求,那么需求方只需要把所有的需求給我們主管就可以,主管會依次看我們的工作量來給我們分配任務,這樣的話,我們前端開發就不需要和多個業務方聯系,我們只需要和我們主管(也就是中介)聯系即可,這樣的好處就弱化了對象之間的耦合。
日常生活中的列子:
中介者模式對于我們日常生活中經常會碰到,比如我們去房屋中介去租房,房屋中介人在租房者和房東出租者之間形成一條中介;租房者并不關心租誰的房,房東出租者也并不關心它租給誰,因為有中介,所以需要中介來完成這場交易。
中介者模式的作用是解除對象與對象之間的耦合關系,增加一個中介對象后,所有的相關對象都通過中介者對象來通信,而不是相互引用,所以當一個對象發送改變時,只需要通知中介者對象即可。中介者使各個對象之間耦合松散,而且可以獨立地改變它們之間的交互。
實現中介者的列子如下:
不知道大家有沒有玩過英雄殺這個游戲,最早的時候,英雄殺有2個人(分別是敵人和自己);我們針對這個游戲先使用普通的函數來實現如下:
比如先定義一個函數,該函數有三個方法,分別是win(贏), lose(輸),和die(敵人死亡)這三個函數;只要一個玩家死亡該游戲就結束了,同時需要通知它的對手勝利了; 代碼需要編寫如下:
function Hero(name) { this.name = name; this.enemy = null; } Hero.prototype.win = function(){ console.log(this.name + 'Won'); } Hero.prototype.lose = function(){ console.log(this.name + 'lose'); } Hero.prototype.die = function(){ this.lose(); this.enemy.win(); } // 初始化2個對象 var h2 = new Hero("朱元璋"); var h3 = new Hero("劉伯溫"); // 給玩家設置敵人 h2.enemy = h3; h3.enemy = h2; // 朱元璋死了 也就輸了 h2.die(); // 輸出 朱元璋lose 劉伯溫Won
現在我們再來為游戲添加隊友
比如現在我們來為游戲添加隊友,比如英雄殺有6人一組,那么這種情況下就有隊友,敵人也有3個;因此我們需要區分是敵人還是隊友需要隊的顏色這個字段,如果隊的顏色相同的話,那么就是同一個隊的,否則的話就是敵人;
我們可以先定義一個數組players來保存所有的玩家,在創建玩家之后,循環players來給每個玩家設置隊友或者敵人;
var players = [];
接著我們再來編寫Hero這個函數;代碼如下:
var players = []; // 定義一個數組 保存所有的玩家 function Hero(name,teamColor) { this.friends = []; //保存隊友列表 this.enemies = []; // 保存敵人列表 this.state = 'live'; // 玩家狀態 this.name = name; // 角色名字 this.teamColor = teamColor; // 隊伍的顏色 } Hero.prototype.win = function(){ // 贏了 console.log("win:" + this.name); }; Hero.prototype.lose = function(){ // 輸了 console.log("lose:" + this.name); }; Hero.prototype.die = function(){ // 所有隊友死亡情況 默認都是活著的 var all_dead = true; this.state = 'dead'; // 設置玩家狀態為死亡 for(var i = 0,ilen = this.friends.length; i < ilen; i+=1) { // 遍歷,如果還有一個隊友沒有死亡的話,則游戲還未結束 if(this.friends[i].state !== 'dead') { all_dead = false; break; } } if(all_dead) { this.lose(); // 隊友全部死亡,游戲結束 // 循環 通知所有的玩家 游戲失敗 for(var j = 0,jlen = this.friends.length; j < jlen; j+=1) { this.friends[j].lose(); } // 通知所有敵人游戲勝利 for(var j = 0,jlen = this.enemies.length; j < jlen; j+=1) { this.enemies[j].win(); } } } // 定義一個工廠類來創建玩家 var heroFactory = function(name,teamColor) { var newPlayer = new Hero(name,teamColor); for(var i = 0,ilen = players.length; i < ilen; i+=1) { // 如果是同一隊的玩家 if(players[i].teamColor === newPlayer.teamColor) { // 相互添加隊友列表 players[i].friends.push(newPlayer); newPlayer.friends.push(players[i]); }else { // 相互添加到敵人列表 players[i].enemies.push(newPlayer); newPlayer.enemies.push(players[i]); } } players.push(newPlayer); return newPlayer; }; // 紅隊 var p1 = heroFactory("aa",'red'), p2 = heroFactory("bb",'red'), p3 = heroFactory("cc",'red'), p4 = heroFactory("dd",'red'); // 藍隊 var p5 = heroFactory("ee",'blue'), p6 = heroFactory("ff",'blue'), p7 = heroFactory("gg",'blue'), p8 = heroFactory("hh",'blue'); // 讓紅隊玩家全部死亡 p1.die(); p2.die(); p3.die(); p4.die(); // lose:dd lose:aa lose:bb lose:cc // win:ee win:ff win:gg win:hh
如上代碼:Hero函數有2個參數,分別是name(玩家名字)和teamColor(隊顏色),
首先我們可以根據隊顏色來判斷是隊友還是敵人;同樣也有三個方法win(贏),lose(輸),和die(死亡);如果每次死亡一個人的時候,循環下該死亡的隊友有沒有全部死亡,如果全部死亡了的話,就輸了,因此需要循環他們的隊友,分別告訴每個隊友中的成員他們輸了,同時需要循環他們的敵人,分別告訴他們的敵人他們贏了;因此每次死了一個人的時候,都需要循環一次判斷他的隊友是否都死亡了;因此每個玩家和其他的玩家都是緊緊耦合在一起了。
下面我們可以使用中介者模式來改善上面的demo;
首先我們仍然定義Hero構造函數和Hero對象原型的方法,在Hero對象的這些原型方法中,不再負責具體的執行的邏輯,而是把操作轉交給中介者對象,中介者對象來負責做具體的事情,我們可以把中介者對象命名為playerDirector;
在playerDirector開放一個對外暴露的接口ReceiveMessage,負責接收player對象發送的消息,而player對象發送消息的時候,總是把自身的this作為參數發送給playerDirector,以便playerDirector 識別消息來自于那個玩家對象。
代碼如下:
var players = []; // 定義一個數組 保存所有的玩家 function Hero(name,teamColor) { this.state = 'live'; // 玩家狀態 this.name = name; // 角色名字 this.teamColor = teamColor; // 隊伍的顏色 } Hero.prototype.win = function(){ // 贏了 console.log("win:" + this.name); }; Hero.prototype.lose = function(){ // 輸了 console.log("lose:" + this.name); }; // 死亡 Hero.prototype.die = function(){ this.state = 'dead'; // 給中介者發送消息,玩家死亡 playerDirector.ReceiveMessage('playerDead',this); } // 移除玩家 Hero.prototype.remove = function(){ // 給中介者發送一個消息,移除一個玩家 playerDirector.ReceiveMessage('removePlayer',this); }; // 玩家換隊 Hero.prototype.changeTeam = function(color) { // 給中介者發送一個消息,玩家換隊 playerDirector.ReceiveMessage('changeTeam',this,color); }; // 定義一個工廠類來創建玩家 var heroFactory = function(name,teamColor) { // 創建一個新的玩家對象 var newHero = new Hero(name,teamColor); // 給中介者發送消息,新增玩家 playerDirector.ReceiveMessage('addPlayer',newHero); return newHero; }; var playerDirector = (function(){ var players = {}, // 保存所有的玩家 operations = {}; // 中介者可以執行的操作 // 新增一個玩家操作 operations.addPlayer = function(player) { // 獲取玩家隊友的顏色 var teamColor = player.teamColor; // 如果該顏色的玩家還沒有隊伍的話,則新成立一個隊伍 players[teamColor] = players[teamColor] || []; // 添加玩家進隊伍 players[teamColor].push(player); }; // 移除一個玩家 operations.removePlayer = function(player){ // 獲取隊伍的顏色 var teamColor = player.teamColor, // 獲取該隊伍的所有成員 teamPlayers = players[teamColor] || []; // 遍歷 for(var i = teamPlayers.length - 1; i>=0; i--) { if(teamPlayers[i] === player) { teamPlayers.splice(i,1); } } }; // 玩家換隊 operations.changeTeam = function(player,newTeamColor){ // 首先從原隊伍中刪除 operations.removePlayer(player); // 然后改變隊伍的顏色 player.teamColor = newTeamColor; // 增加到隊伍中 operations.addPlayer(player); }; // 玩家死亡 operations.playerDead = function(player) { var teamColor = player.teamColor, // 玩家所在的隊伍 teamPlayers = players[teamColor]; var all_dead = true; //遍歷 for(var i = 0,player; player = teamPlayers[i++]; ) { if(player.state !== 'dead') { all_dead = false; break; } } // 如果all_dead 為true的話 說明全部死亡 if(all_dead) { for(var i = 0, player; player = teamPlayers[i++]; ) { // 本隊所有玩家lose player.lose(); } for(var color in players) { if(color !== teamColor) { // 說明這是另外一組隊伍 // 獲取該隊伍的玩家 var teamPlayers = players[color]; for(var i = 0,player; player = teamPlayers[i++]; ) { player.win(); // 遍歷通知其他玩家win了 } } } } }; var ReceiveMessage = function(){ // arguments的第一個參數為消息名稱 獲取第一個參數 var message = Array.prototype.shift.call(arguments); operations[message].apply(this,arguments); }; return { ReceiveMessage : ReceiveMessage }; })(); // 紅隊 var p1 = heroFactory("aa",'red'), p2 = heroFactory("bb",'red'), p3 = heroFactory("cc",'red'), p4 = heroFactory("dd",'red'); // 藍隊 var p5 = heroFactory("ee",'blue'), p6 = heroFactory("ff",'blue'), p7 = heroFactory("gg",'blue'), p8 = heroFactory("hh",'blue'); // 讓紅隊玩家全部死亡 p1.die(); p2.die(); p3.die(); p4.die(); // lose:aa lose:bb lose:cc lose:dd // win:ee win:ff win:gg win:hh
我們可以看到如上代碼;玩家與玩家之間的耦合代碼已經解除了,而把所有的邏輯操作放在中介者對象里面進去處理,某個玩家的任何操作不需要去遍歷去通知其他玩家,而只是需要給中介者發送一個消息即可,中介者接受到該消息后進行處理,處理完消息之后會把處理結果反饋給其他的玩家對象。使用中介者模式解除了對象與對象之間的耦合代碼; 使程序更加的靈活.
中介者模式實現購買商品的列子
下面的列子是書上的列子,比如在淘寶或者天貓的列子不是這樣實現的,也沒有關系,我們可以改動下即可,我們最主要來學習下使用中介者模式來實現的思路。
首先先介紹一下業務:在購買流程中,可以選擇手機的顏色以及輸入購買的數量,同時頁面中有2個展示區域,分別顯示用戶剛剛選擇好的顏色和數量。還有一個按鈕動態顯示下一步的操作,我們需要查詢該顏色手機對應的庫存,如果庫存數量小于這次的購買數量,按鈕則被禁用并且顯示庫存不足的文案,反之按鈕高亮且可以點擊并且顯示假如購物車。
HTML代碼如下:
選擇顏色:
<select id="colorSelect"> <option value="">請選擇</option> <option value="red">紅色</option> <option value="blue">藍色</option> </select> <p>輸入購買的數量: <input type="text" id="numberInput"/></p> 你選擇了的顏色:<div id="colorInfo"></div> <p>你輸入的數量: <div id="numberInfo"></div> </p> <button id="nextBtn" disabled="true">請選擇手機顏色和購買數量</button>
首先頁面上有一個select選擇框,然后有輸入的購買數量輸入框,還有2個展示區域,分別是選擇的顏色和輸入的數量的顯示的區域,還有下一步的按鈕操作;
我們先定義一下:
假設我們提前從后臺獲取到所有顏色手機的庫存量
var goods = { // 手機庫存 "red": 6, "blue": 8 };
接著 我們下面分別來監聽colorSelect的下拉框的onchange事件和numberInput輸入框的oninput的事件,然后在這兩個事件中作出相應的處理
常規的JS代碼如下:
// 假設我們提前從后臺獲取到所有顏色手機的庫存量 var goods = { // 手機庫存 "red": 6, "blue": 8 }; /* 我們下面分別來監聽colorSelect的下拉框的onchange事件和numberInput輸入框的oninput的事件, 然后在這兩個事件中作出相應的處理 */ var colorSelect = document.getElementById("colorSelect"), numberInput = document.getElementById("numberInput"), colorInfo = document.getElementById("colorInfo"), numberInfo = document.getElementById("numberInfo"), nextBtn = document.getElementById("nextBtn"); // 監聽change事件 colorSelect.onchange = function(e){ select(); }; numberInput.oninput = function(){ select(); }; function select(){ var color = colorSelect.value, // 顏色 number = numberInput.value, // 數量 stock = goods[color]; // 該顏色手機對應的當前庫存 colorInfo.innerHTML = color; numberInfo.innerHTML = number; // 如果用戶沒有選擇顏色的話,禁用按鈕 if(!color) { nextBtn.disabled = true; nextBtn.innerHTML = "請選擇手機顏色"; return; } // 判斷用戶輸入的購買數量是否是正整數 var reg = /^\d+$/g; if(!reg.test(number)) { nextBtn.disabled = true; nextBtn.innerHTML = "請輸入正確的購買數量"; return; } // 如果當前選擇的數量大于當前的庫存的數量的話,顯示庫存不足 if(number > stock) { nextBtn.disabled = true; nextBtn.innerHTML = "庫存不足"; return; } nextBtn.disabled = false; nextBtn.innerHTML = "放入購物車"; }
上面的代碼雖然是完成了頁面上的需求,但是我們的代碼都耦合在一起了,目前雖然問題不是很多,假如隨著以后需求的改變,SKU屬性越來越多的話,比如頁面增加一個或者多個下拉框的時候,代表選擇手機內存,現在我們需要計算顏色,內存和購買數量,來判斷nextBtn是顯示庫存不足還是放入購物車;代碼如下:
HTML代碼如下:
選擇顏色: <select id="colorSelect"> <option value="">請選擇</option> <option value="red">紅色</option> <option value="blue">藍色</option> </select> <br/> <br/> 選擇內存: <select id="memorySelect"> <option value="">請選擇</option> <option value="32G">32G</option> <option value="64G">64G</option> </select> <p>輸入購買的數量: <input type="text" id="numberInput"/></p> 你選擇了的顏色:<div id="colorInfo"></div> 你選擇了內存:<div id="memoryInfo"></div> <p>你輸入的數量: <div id="numberInfo"></div> </p> <button id="nextBtn" disabled="true">請選擇手機顏色和購買數量</button>
JS代碼變為如下:
// 假設我們提前從后臺獲取到所有顏色手機的庫存量 var goods = { // 手機庫存 "red|32G": 6, "red|64G": 16, "blue|32G": 8, "blue|64G": 18 }; /* 我們下面分別來監聽colorSelect的下拉框的onchange事件和numberInput輸入框的oninput的事件, 然后在這兩個事件中作出相應的處理 */ var colorSelect = document.getElementById("colorSelect"), memorySelect = document.getElementById("memorySelect"), numberInput = document.getElementById("numberInput"), colorInfo = document.getElementById("colorInfo"), numberInfo = document.getElementById("numberInfo"), memoryInfo = document.getElementById("memoryInfo"), nextBtn = document.getElementById("nextBtn"); // 監聽change事件 colorSelect.onchange = function(){ select(); }; numberInput.oninput = function(){ select(); }; memorySelect.onchange = function(){ select(); }; function select(){ var color = colorSelect.value, // 顏色 number = numberInput.value, // 數量 memory = memorySelect.value, // 內存 stock = goods[color + '|' +memory]; // 該顏色手機對應的當前庫存 colorInfo.innerHTML = color; numberInfo.innerHTML = number; memoryInfo.innerHTML = memory; // 如果用戶沒有選擇顏色的話,禁用按鈕 if(!color) { nextBtn.disabled = true; nextBtn.innerHTML = "請選擇手機顏色"; return; } // 判斷用戶輸入的購買數量是否是正整數 var reg = /^\d+$/g; if(!reg.test(number)) { nextBtn.disabled = true; nextBtn.innerHTML = "請輸入正確的購買數量"; return; } // 如果當前選擇的數量大于當前的庫存的數量的話,顯示庫存不足 if(number > stock) { nextBtn.disabled = true; nextBtn.innerHTML = "庫存不足"; return; } nextBtn.disabled = false; nextBtn.innerHTML = "放入購物車"; }
關于“javascript設計模式之中介者模式的示例分析”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。