使用策略模式封装拦截器

Posted mn6364

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用策略模式封装拦截器相关的知识,希望对你有一定的参考价值。

通过if-else 来实现拦截器的封装

axios.interceptors.response.use((res) => 
  let message, statusCode = res.data.data
  //  退出登录状态码
  let logoutCodes = new Set([435001, 435011, 436050])
  if (statusCode === 1000) 
    //  更新全局token
    let pragma = res.headers
    if (pragma) window.token = pragma
    //  返回数据
    return res.data.data

   else if (logoutCodes.has(statusCode)) 
    setTimeout(() => window.logout(), 1000)
    return Promise.reject(message)
   else 
    return Promise.reject(message,statusCode)
  
, (error) => 
  return Promise.reject(error.response.data)
)

首先,说一下上面拦截器封装的逻辑,当状态码为1000的时候,请求数据成功,当状态码为435001, 435011, 436050的时候,退出登录。其他状态码的时候,返回错误信息。 在最开始封装拦截器的时候,使用了大量的if-else的。在可读性上是不太 友好的,而且,后期的维护也不是很友好。 最近,正好在学习设计模式,感觉这个可以通过策略模式来进行优化.

策略模式就是将一系列的算法单独封装起来,并且他们可以相互替换。策略模式有两个类:一是策略类,二是环境类。策略类封装了具体的算法,并负责具体的计算过程。环境类是接收客户端的请求,随后把请求委托给某一个策略类。

第一次使用策略模式进行的封装

// 定义策略类
let Policy = 
  // 状态码满足1000的情况下
  success: function(res) 
    let pragma = res.headers;
    pragma && (window.token = pragma);
    //  返回数据
    return res.data.result
  ,
  // 状态码满足435001,435011, 436050情况下,登出
  logout: function(res) 
    let message = res.data;
    setTimeout(() => window.logout(), 1000)
    return Promise.reject(message)
  ,
  // 状态码满足其他情况下
  other: function() 
    let message, statusCode = res.data
    return Promise.reject(message,statusCode)
  

/**
 * 响应拦截器
 * @author liuqiuyue
 * @date 2019-04-29
 */
axios.interceptors.response.use((res) => 
  let statusCode = res.data
  //  退出登录状态码
  let logoutCodes = new Set([435001, 435011, 436050])
  let codeBol = (statusCode === 1000);
  let logoutBol = (logoutCodes.has(statusCode));
  // 满足状态码为1000的时候,执行的方法
  codeBol && Policy.success(res);
  // 状态码满足435001,435011, 436050情况下,登出
  !codeBol && logoutBol && Policy.logout(res);
  // 状态码满足其他情况下
  !codeBol && !logoutBol && Policy.other(res);
, (error) => 
  return Promise.reject(error.response.data)
)

封装了一个对象,这个对象里面含有不同的方法,在满足条件的时候,去走不同策略类中的方法。看似是策略模式,我也一直这么认为,这是符合策略模式的。之前也经常认为中写法是符合策略模式的。经高人指点之后,发现,这其实不算一个真正的策略模式,可以说是一个伪策略模式。为什么这么说呢? 推荐阅读 https://www.runoob.com/?s=%E7%AD%96%E7%95%A5%E6%A8%A1%E5%BC%8

上面的代码 中Policy是对一系列的算法进行了封装,但是会发现,其实是没有环境类的,只是通过不同的条件,去调取不同的方法的。所以,他是伪策略模式。

对策略模式进行二次封装 通过一个加减乘除的算法的案例来解释

策略类

function computed() 
    

computed.prototype.add = function(a, b) 
    console.log(走了嘛)
    return a+b

computed.prototype.subtraction = function(a, b) 
    return a-b

computed.prototype.Multiply = function(a,b) 
    return a*b

computed.prototype.except = function(a, b) 
    return a/b

环境类

// 定义了环境类
function context() 
    

context.prototype.init= function(a, b) 
    this.a =a;
    this.b = b;
    console.log(数值初始化, this.a, this.b)

context.prototype.getWay = function(way) 
    console.log(way, way)
    return way(this.a, this.b)
    

客户端的请求,具体的实现

var c = new context()
c.init(10, 20)
let com = new computed();
c.getWay(com.add)
console.log(结果, c.getWay(com.add))

在解释这种说法之前,先说一下面向对象的概念,

(1)类,有相同的特征和行为的事物的抽象,

( 2)对象 :类的一个实例。

那么。js是面向对象语言嘛?

准确点说,js是一种基于面向对象的语言,因为,她没有提供抽象,继承,重载等有关面向对象语言的许多功能,而是把其他语言所创建的复杂对象统一起来,从而形成一个非常强大的对象系统,这种独特性称它为prototype_basedOO(基于原型的面向对象)。传统的是class-basedOO(基于类的面向对象)

上面的这种写法就是使用的js的基于原型的面向对象去实现的策略模式。

下面,通过传统的基于类的面向对象思想进行封装

Strategy抽象类

export class Strategy 
    // 抽象类
    constructor() 

    
    init(num1, num2) 
        console.log(抽象类, num1, num2)
        this.num1 = num1;
        this.num2 =num2;
    

Add方法,继承于Strategy类

import  Strategy from  ../js/Strategy
export class Add extends Strategy
    constructor(num1, num2) 
        super(num1, num2)
    
    init(num1, num2) 
        console.log(数据, num1, num2)
        return num1+num2
    

Context环境类

// 环境类
let Strategy = require(../js/Strategy)
let strategy = new Strategy()
export  class Context 
    constructor() 
        this.strategy =strategy
    
    // 定义抽象类的方式
    initWay(way) 
        // 数据的初始化
        this.strategy = way
        console.log(数据的初始化,  this.strategy)
    
    // 计算
    getWay(num1, num2) 
        console.log(获取对应的方法,  num1, num2)
        console.log(结果, this.strategy.init(num1, num2))
        return this.strategy.init(num1, num2)
    

实现

var contenx = new Context()
context.getWay(add)

 

以上是关于使用策略模式封装拦截器的主要内容,如果未能解决你的问题,请参考以下文章

spring中如何使用策略模式

JavaScript设计模式:策略模式

行为型模式之策略模式

《设计模式之禅》之策略模式

JavaScript设计模式中策略模式的使用方法

策略模式(封装算法和规则)