JS設計模式五:職責鏈模式

職責鏈模式簡述

職責連是由多個不同的對象組成的,有發送者跟接收者,分別負責信息的發送跟接收,其中,鏈中第一個對象是 職責連是由多個不同的對象組成的,發送者是發送請求的對象,接收者接收請求并且對其進行處理或傳遞的對象。基本流程如下:

  1. 發送者知道鏈中的第一個接收者,它向這個接收者發送該請求。
  2. 每一個接收者都對請求進行分析,然后要么處理它,要么它往下傳遞。
  3. 每一個接收者知道其他的對象只有一個,即它在鏈中的下家(successor)。
  4. 如果沒有任何接收者處理請求,那么請求會從鏈中離開。

職責鏈模式是個鏈式結構,請求在鏈中的節點之間依次傳遞,直到有一個對象能處理該請求為止。如果沒有任何對象處理該請求的話,那么請求就會從鏈中離開。

實戰

以電商網站抽獎為例,規則如下:

  1. 用戶充值500元,可以100%中獎100元紅包
  2. 用戶充值200元,可以100%中獎20元紅包
  3. 用戶不充值,也可以抽獎,但概率極低。
  4. 用戶充值失敗,按不充值處理。

常規實現

首先需要定義幾個字段:

  1. orderType:充值類型。如果值為1的話,說明是充值500元的用戶,如果為2的話,說明是充值200元的用戶,如果是3的話,說明是沒有充值的用戶。
  2. isPay:是否已經成功充值了。 如果該值為true的話,說明已經成功充值了,否則的話說明沒有充值成功;就當作普通用戶來購買。
  3. count:表示數量。普通用戶抽獎,如果數量有的話,就可以拿到優惠卷,否則的話,不能拿到優惠卷。

實現如下:

var order =  function(orderType,isPay,count) {if(orderType == 1) {  // 用戶充值500元if(isPay == true) { // 如果充值成功的話,100%中獎console.log("親愛的用戶,您中獎了100元紅包了");}else {// 充值失敗,就當作普通用戶來處理中獎信息if(count > 0) {console.log("親愛的用戶,您已抽到10元優惠卷");}else {console.log("親愛的用戶,請再接再厲哦");}}}else if(orderType == 2) {  // 用戶充值200元if(isPay == true) {     // 如果充值成功的話,100%中獎console.log("親愛的用戶,您中獎了20元紅包了");}else {// 充值失敗,就當作普通用戶來處理中獎信息if(count > 0) {console.log("親愛的用戶,您已抽到10元優惠卷");}else {console.log("親愛的用戶,請再接再厲哦");}}}else if(orderType == 3) {// 普通用戶來處理中獎信息if(count > 0) {console.log("親愛的用戶,您已抽到10元優惠卷");}else {console.log("親愛的用戶,請再接再厲哦");}}
};
復制代碼

如上代碼,雖然實現了需求,但存在的問題也比較突出: 一、業務邏輯代碼耦合度太高,如果想增加條件,比如充值300可以中獎150元紅包,這時候就很容易改出問題 二、冗余代碼太多,普通用戶抽獎的代碼是可以單獨抽離出來的

職責鏈實現

function order500(orderType,isPay,count){if(orderType == 1 && isPay == true)    {console.log("親愛的用戶,您中獎了100元紅包了");}else {//我不知道下一個節點是誰,反正把請求往后面傳遞return "nextSuccessor";}
};
function order200(orderType,isPay,count) {if(orderType == 2 && isPay == true) {console.log("親愛的用戶,您中獎了20元紅包了");}else {//我不知道下一個節點是誰,反正把請求往后面傳遞return "nextSuccessor";}
};
function orderNormal(orderType,isPay,count){// 普通用戶來處理中獎信息if(count > 0) {console.log("親愛的用戶,您已抽到10元優惠卷");}else {console.log("親愛的用戶,請再接再厲哦");}
}
// 下面需要編寫職責鏈模式的封裝構造函數方法
var Chain = function(fn){this.fn = fn;this.successor = null;
};
Chain.prototype.setNextSuccessor = function(successor){return this.successor = successor;
}
// 把請求往下傳遞
Chain.prototype.passRequest = function(){var ret = this.fn.apply(this,arguments);if(ret === 'nextSuccessor') {return this.successor && this.successor.passRequest.apply(this.successor,arguments);}return ret;
}
//現在我們把3個函數分別包裝成職責鏈節點:
var chainOrder500 = new Chain(order500);
var chainOrder200 = new Chain(order200);
var chainOrderNormal = new Chain(orderNormal);// 然后指定節點在職責鏈中的順序
chainOrder500.setNextSuccessor(chainOrder200);
chainOrder200.setNextSuccessor(chainOrderNormal);//最后把請求傳遞給第一個節點:
chainOrder500.passRequest(1,true,500);  // 親愛的用戶,您中獎了100元紅包了
chainOrder500.passRequest(2,true,500);  // 親愛的用戶,您中獎了20元紅包了
chainOrder500.passRequest(3,true,500);  // 親愛的用戶,您已抽到10元優惠卷 
chainOrder500.passRequest(1,false,0);   // 親愛的用戶,請再接再厲哦
復制代碼

如上代碼: 一、分別編寫order500,order200,orderNormal三個函數,處理自己的業務邏輯,如果自己的函數不能處理的話,就返回字符串nextSuccessor 往后面傳遞 二、封裝Chain構造函數,接收fn做為參數,且帶有屬性successor。實例化后的Chain類型的對象,就像一個一個獨立存在的節點。 三、Chain構造函數原型上有2個方法,分別是setNextSuccessor 和 passRequest。setNextSuccessor 方法指定了節點在職責鏈中的順序,passRequest方法是將請求轉移到職責鏈的下一個節點。

如上文提到的,假設需要實現“充值300中獎150元”,我們可以編寫order300這個函數,通過Chain包裝起來,指定在職責鏈中的順序即可。業務邏輯的代碼不需要任何處理。

現在又有一個問題,我們在開發中經常會碰到ajax異步請求,如果我們用上面的做法,就不生效了。由此,便引出了異步的職責鏈來解決這個問題。我們給Chain類再增加一個原型方法Chain.prototype.next,表示手動傳遞請求給職責鏈中的一下個節點。

function Fn1() {console.log(1);return "nextSuccessor";
}
function Fn2() {console.log(2);var self = this;setTimeout(function(){self.next();},1000);
}
function Fn3() {console.log(3);
}
// 下面需要編寫職責鏈模式的封裝構造函數方法
var Chain = function(fn){this.fn = fn;this.successor = null;
};
Chain.prototype.setNextSuccessor = function(successor){return this.successor = successor;
}
// 把請求往下傳遞
Chain.prototype.passRequest = function(){var ret = this.fn.apply(this,arguments);if(ret === 'nextSuccessor') {return this.successor && this.successor.passRequest.apply(this.successor,arguments);}return ret;
}
Chain.prototype.next = function(){return this.successor && this.successor.passRequest.apply(this.successor,arguments);
}
//現在我們把3個函數分別包裝成職責鏈節點:
var chainFn1 = new Chain(Fn1);
var chainFn2 = new Chain(Fn2);
var chainFn3 = new Chain(Fn3);// 然后指定節點在職責鏈中的順序
chainFn1.setNextSuccessor(chainFn2);
chainFn2.setNextSuccessor(chainFn3);chainFn1.passRequest();  // 打印出1,2 過1秒后 會打印出3
復制代碼

如上代碼,當執行到F2時,遇到了定時器異步函數,當定時器執行結束后,調用了next方法,手動將請求交給職責鏈中的下一個節點,因此過了一秒后,會打印3。

總結

優點

  1. 解耦了請求發送者和度個接收者之間的復雜關系,不需要知道鏈中哪個節點能處理你的請求,只需要把請求傳遞到第一個節點即可。
  2. 鏈中的節點對象可以靈活地拆分重組,增加或刪除一個節點,或者改變節點的位置都是很簡單的事情。
  3. 我們還可以手動指定節點的起始位置,并不是說非得要從其實節點開始傳遞的.

缺點

職責鏈模式中多了一點節點對象,可能在某一次請求過程中,大部分節點沒有起到實質性作用,他們的作用只是讓請求傳遞下去,從性能方面考慮,避免過長的職責鏈提高性能。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/281390.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/281390.shtml
英文地址,請注明出處:http://en.pswp.cn/news/281390.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

web框架之Django(一)

Python的WEB框架有Django、Tornado、Flask 等多種,Django相較與其他WEB框架其優勢為:大而全,框架本身集成了ORM、模型綁定、模板引擎、緩存、Session等諸多功能。 基本配置 一、創建django程序 終端命令:django-admin startprojec…

寫一個易于維護使用方便性能可靠的Hybrid框架(一)—— 思路構建

寫一個易于維護使用方便性能可靠的Hybrid框架(二)—— 插件化 寫一個易于維護使用方便性能可靠的Hybrid框架(三)—— 配置插件 前言 本來上一篇博文寫完,我就告訴自己,這是最后一篇,之后不再總結…

程序員制作出價值5億外賣神器卻不能取消訂單,你知道嗎?

小編今日給大家帶來RACDisopsable,大家可能有部分人對這個會感覺到很陌生,那么我就用一句話來表達就是他可以幫我們取消訂閱。那么又會有人會對這個產生疑問了,我們什么時候需要用到這個取消訂閱了打個實際的例子來說吧,今天我在餓…

Computer

鏈接&#xff1a;http://acm.hdu.edu.cn/showproblem.php?pid2196https://blog.csdn.net/shuangde800/article/details/9732825#include<iostream> #include<cstdio> #include<algorithm> #include<vector> #include<queue> #include<cmath&…

智慧“昆明”在路上 未來充滿精彩

智慧城市是運用物聯網、云計算、大數據、移動互聯網、空間地理信息集成等新一代信息技術&#xff0c;促進城市規劃、建設、管理和服務智慧化的新理念和新模式。近年來&#xff0c;昆明市全面加快智慧城市建設&#xff0c;力爭通過三年的努力&#xff0c;打造區域信息輻射中心的…

《精讀 Mastering ABP Framework》教程發布

精讀《Mastering ABP Framework》學習總結&#xff0c;掌握軟件開發最佳實踐&#xff0c;構建可維護 .NET 解決方案。從 ABP Framework 框架中學習如何構建現代 WEB 應用程序。掌握 ABP Framework 框架ABP Framework 是一個完整的基礎架構&#xff0c;遵循軟件開發最佳實踐&…

C# 委托知識總結

1.什么是委托&#xff0c;為什么要使用委托 我正在埋頭苦寫程序&#xff0c;突然想喝水&#xff0c;但是又不想自己去掉杯水而打斷自己的思路&#xff0c;于是我就想讓女朋友去給我倒水。她去給我倒水&#xff0c;首先我得讓她知道我想讓她干什么&#xff0c;通知她之后我可以繼…

阿里云大學課程學習有獎征文活動現在開始

2019獨角獸企業重金招聘Python工程師標準>>> "學有所獲&#xff0c;分享為美"--阿里云大學課程學習有獎征文活動開始啦~~ 看課程&#xff0c;寫心得&#xff0c;贏千元大獎&#xff0c;還有機會加入阿里云大學技術作者群&#xff01;想試試自己的技術文筆…

配置網絡測試環境的批處理

引言 有次需要測試 50 臺左右的設備&#xff0c;每個都要連上電腦并搭好測試環境。這種事當然用服務器下發配置最方便&#xff0c;但條件不允許哦&#xff0c;只得手工一臺臺設。 寫了個批處理配置腳本&#xff0c;放到 U 盤上&#xff0c;最好再配上 autorun.inf&#xff0c;嘿…

Android 的系統架構

Android 的系統架構和其它操作系統一樣&#xff0c;采用了分層的架構。android 分為四個層&#xff0c;從高層到低層分別是應用程序層、應用程序框架層、系統運行庫層和 linux 核心層。 Android 是以 Linux 為核心的手機操作平臺&#xff0c;作為一款開放式的操作系統&#xf…

記一次 .NET 某制造業 MES 系統崩潰分析

一&#xff1a;背景 1.講故事前段時間有位朋友微信找到我&#xff0c;說他的程序偶爾會出現內存溢出崩潰&#xff0c;讓我幫忙看下是怎么回事&#xff0c;咨詢了下程序是 x86 部署&#xff0c;聽到這個詞其實心里已經有了數&#xff0c;不管怎么樣還是用 windbg 分析一下。二&a…

HTTPS協議開通,Apache服務器CSR簽名申請

登錄您的服務器終端 (SSH)。在命令提示符下&#xff0c;鍵入以下命令&#xff1a;openssl req -new -newkey rsa:2048 -nodes -keyout yourdomain.key -out yourdomain.csr將 yourdomain 替換為您要保護的域名。例如&#xff0c;如果您的域名是 coolexample.com&#xff0c;您就…

首次公開!單日600PB的計算力--阿里巴巴EB級大數據平臺的進擊

摘要&#xff1a; 每年的雙11之前&#xff0c;也是MaxCompute各種乾坤大挪移落定的時候&#xff0c;因為雙11就是各種大折騰項目的自然deadline。在今年雙11之前&#xff0c;一路向北遷移和在離線混部項目&#xff0c;將杭州集群除螞蟻外整體遷移到張北&#xff0c;涉及了絕大部…

軟件測試金字塔

軟件測試金字塔 在敏捷方法中&#xff0c;持續集成是其基石&#xff0c;持續集成的核心是自動化測試。下面這篇關于測試金字塔的文章&#xff0c;來自大師Martin Fowler。 測試金字塔的概念來自Mike Cohn&#xff0c;在他的書Succeeding With Agile中有詳細描述&#xff1a;測試…

使用pm2守護你的.NET Core應用程序

簡介PM2是常用的node進程管理工具&#xff0c;它可以提供node.js應用管理&#xff0c;如自動重載、性能監控、負載均衡等。同類工具有Supervisor、Forever等。pm2是一個進程管理工具,可以用它來管理你的node進程&#xff0c;并查看node進程的狀態&#xff0c;當然也支持性能監控…

C-指針02 2017/11/24

/* 復習 1.指針類型 int *指針類型 指針指向的變量類型指針指向哪個變量2.基本數據類型 4種指針類型 存放的地址 和系統有關系 4個字節數組類型結構體 枚舉 聯合3.指針加法減法 p 和數組搭配使用4.兩個運算符 *取值(解引用) &取地址5. *(pi) p[i] …

程序員搞笑段子

轉載于:https://www.cnblogs.com/Zhusi/p/10083474.html

學習之旅——工作記錄日志2017.7.09

1.例子&#xff1a;在dev_lala上開發完畢后&#xff0c;切換到dev分支&#xff0c;在此分支上pull最新的代碼來保證dev上的代碼是最新的。在dev分支上git branch -b haha一個新的分支haha&#xff0c; 用git log dev_lala查看提交記錄&#xff0c;將我自己的幾個記錄加到haha分…

Git常用命令與基本操作

Git操作指令系統配置基本命令獲取/刪除Git倉庫更新記錄撤銷操作遠程倉庫的使用分支系統系統配置 git config 為系統自帶的配置指令&#xff0c;它可以控制GIT的行為和外觀 配置用戶信息 git config --global user.name "John Doe" git config --global user.email …

CA周記 - 在 Azure ML 上用 .NET 跑機器學習

.NET 是一個跨平臺&#xff0c;全場景應用的開源技術。你有在用 .NET 做機器學習/深度學習的應用嗎&#xff1f;如果從框架角度&#xff0c;ML.NET / Tensorflow.NET / 不斷在進步的 TorchSharp 通過幾年的發展已經開始穩定&#xff0c;但如果在一些大型項目上&#xff0c;特別…