zoukankan      html  css  js  c++  java
  • 使用策略模式封装拦截器

    通过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)
  • 相关阅读:
    多线程 NSThread GCD
    UICollectionView 集合视图用法,自定义Cell
    简单的注册 登录
    数据库sqlite的使用
    沙盒机制 归档 反归档
    图片异步加载 ,KVO
    iOS开发系列--通知与消息机制
    制作iOS Ad-Hoc测试应用
    NT_iOS笔记—判断iPhone6
    iOS开发多线程篇—单例模式(ARC)
  • 原文地址:https://www.cnblogs.com/mn6364/p/11070040.html
Copyright © 2011-2022 走看看