使用策略模式封装拦截器

通过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)

 

posted @ 2019-06-22 19:13  栀子花编织着留恋  阅读(367)  评论(0编辑  收藏  举报