沐鳴網址_框架源碼中用來提高擴展性的設計模式

用過Axios的朋友應該知道,Axios的攔截器有請求攔截器和響應攔截器,執行的順序是請求攔截器 -> 發起請求 -> 響應攔截器,這其實就是一個鏈條上串起了三個職責。下面我們來看看這個鏈條怎麼實現:,
,我們寫的代碼都是為了一定的需求服務的,但是這些需求並不是一成不變的,當需求變更了,如果我們代碼的擴展性很好,我們可能只需要簡單的添加或者刪除模塊就行了,如果擴展性不好,可能所有代碼都需要重寫,那就是一場災難了,所以提高代碼的擴展性是勢在必行的。怎樣才算有好的擴展性呢?好的擴展性應該具備以下特徵:,實例:Axios攔截器,// 先從用法入手,一般我們添加攔截器是這樣寫的
// instance.interceptors.request.use(fulfilled, rejected)
// 根據這個用法我們先寫一個Axios類。
function Axios() {
// 實例上有個interceptors對象,裏面有request和response兩個屬性
// 這兩個屬性都是InterceptorManager的實例
this.interceptors = {
request:
new InterceptorManager(),
response:
new InterceptorManager() }; }
// 然後是實現InterceptorManager類
function InterceptorManager() {
// 實例上有一個數組,存儲攔截器方法
this.handlers = []; }
// InterceptorManager有一個實例方法use InterceptorManager.prototype.use =
function(fulfilled, rejected) {
// 這個方法很簡單,把傳入的回調放到handlers裏面就行
this.handlers.push({ fulfilled, rejected }) },實例:職責鏈組織表單驗證,// 前端驗證先寫個方法
function frontEndValidator(inputValue) {
return
Promise.resolve(inputValue);
// 注意返回值是個promise }
// 後端驗證也寫個方法
function backEndValidator(inputValue) {
return
Promise.resolve(inputValue); }
// 寫一個驗證器
function validator(inputValue) {
// 仿照Axios,將各個步驟放入一個數組
const validators = [frontEndValidator, backEndValidator];
// 前面Axios是循環調用promise.then來執行的職責鏈,我們這裏換個方式,用async來執行下
async
function runValidate() {
let result = inputValue;
while(validators.length) { result =
await validators.shift()(result); }
return result; }
// 執行runValidate,注意返回值也是一個promise runValidate().then(
(res) => {
console.log(res)}); }
// 上述代碼已經可以執行了,只是我們沒有具體的校驗邏輯,輸入值會原封不動的返回 validator(
123);
// 輸出: 123,上述代碼是從Axios源碼中精簡出來的,可以看出他巧妙的運用了職責鏈模式,將需要做的任務組織成一個鏈條,這個鏈條上的任務相互不影響,攔截器可有可無,而且可以有多個,兼容性非常強。,上面的代碼其實就完成了攔截器創建和use的邏輯,並不複雜,那這些攔截器方法都是什麼時候執行呢?當然是我們調用instance.request的時候,調用instance.request的時候真正執行的就是請求攔截器 -> 發起請求 -> 響應攔截器鏈條,所以我們還需要來實現下Axios.prototype.request:,Axios.prototype.request =
function(config) {
// chain裏面存的就是我們要執行的方法鏈條
// dispatchRequest是發起網絡請求的方法,本文主要講設計模式,這個方法就不實現了
// chain裏面先把發起網絡請求的方法放進去,他的位置應該在chain的中間
const chain = [dispatchRequest,
undefined];
// chain前面是請求攔截器的方法,從request.handlers裏面取出來放進去
this.interceptors.request.handlers.forEach(
function unshiftRequestInterceptors(interceptor) { chain.unshift(interceptor.fulfilled, interceptor.rejected); });
// chain後面是響應攔截器的方法,從response.handlers裏面取出來放進去
this.interceptors.response.handlers.forEach(
function pushResponseInterceptors(interceptor) { chain.push(interceptor.fulfilled, interceptor.rejected); });
// 經過上述代碼的組織,chain這時候是這樣的:
// [request.fulfilled, request.rejected, dispatchRequest, undefined, response.fulfilled,
// response.rejected]
// 這其實已經按照請求攔截器 -> 發起請求 -> 響應攔截器的順序排好了,拿來執行就行
let promise =
Promise.resolve(config);
// 先來個空的promise,好開啟then
while (chain.length) {
// 用promise.then進行鏈式調用 promise = promise.then(chain.shift(), chain.shift()); }
return promise; },當然是從優秀的代碼身上學習了,本文會深入Axios,Node.js,vue等優秀框架,從他們源碼總結幾種設計模式出來,然後再用這些設計模式嘗試解決下工作中遇到的問題。本文主要會講職責鏈模式,觀察者模式,適配器模式,裝飾器模式。下面一起來看下吧:,
,職責鏈模式顧名思義就是一個鏈條,這個鏈條上串聯了很多的職責,一個事件過來,可以被鏈條上的職責依次處理。他的好處是鏈條上的各個職責,只需要關心自己的事情就行了,不需要知道自己的上一步是什麼,下一步是什麼,跟上下的職責都不耦合,這樣當上下職責變化了,自己也不受影響,往鏈條上添加或者減少職責也非常方便。,用過Axios的朋友應該知道,Axios的攔截器有請求攔截器和響應攔截器,執行的順序是請求攔截器 -> 發起請求 -> 響應攔截器,這其實就是一個鏈條上串起了三個職責。下面我們來看看這個鏈條怎麼實現: