js设计模式——适配器模式

145 阅读2分钟

什么是适配器模式?

举一个我工作中的例子:某一天,我觉得公司自带的键盘不好用,我想用自己的机械键盘。正当我从家里把键盘一路扛到公司时,发现!公司电脑USB是被禁用的(说是防泄密...)!

我心想:“难道要新买一把圆头接口的机械键盘了?”。其实大可不必,一个USB转圆头的适配器就可以帮我搞定这个兼容问题。此时这个适配器,就可以理解为设计模式中的适配器

应用场景

背景

某一天,我在浏览技术文章时,发现了一个fetch方法,可以用来发送请求。而且还返回promise

我心想,这不错啊,用起来可比ajax简洁多了。说时迟那时快,立刻开始封装~

// httpUtils.js
class HttpUtils {
  static doGet(url) {
    return new Promise((resolve, reject) => {
      fetch(url).then(res => res.json()).then(res => {
        resolve(res)
      }).catch(err => {
        reject(err)
      })
    })
  }
  static doPost(url, data) {
    return new Promise((resolve, reject) => {
      fetch(url, {
        method: 'POST',
        headers: {
          Accept: 'application/json',
          'Content-Type': 'application/x-www-form-urlencoded'
        },
        // 将object类型的数据格式化为合法的body参数
        body: this.changeData(data)
      }).then(res => res.json()).then(res => {
        resolve(res)
      }).catch(err => {
        reject(err)
      })
    })
  }
  static changeData(obj) {
    var prop,
      str = ''
    var i = 0
    for (prop in obj) {
      if (!prop) {
        return
      }
      if (i == 0) {
        str += prop + '=' + obj[prop]
      } else {
        str += '&' + prop + '=' + obj[prop]
      }
      i++
    }
    return str
  }
}

// 使用时:
const url = 'https://api.github.com/users/ygunoil'
const params = { name: 'xxx' }

const postResponse = HttpUtils.doPost(url, params)
const getResponse = HttpUtils.doGet(url)

封装完后,开心了没几天,组长发现我封装的方法说到:“小伙子不错,我们现在把系统里所有的方法统一一下,就用你这个HttpUtils方法来发送请求吧。”我人懵了,因为我知道,之前的请求封装的是XMLHttpRequest,关键是,连入参和调用方式都不一样。

// 老旧的请求发送方式
/*
    url,请求路径
    method,请求方法
    params,请求参数
    success:请求成功的回调
    fail:请求失败的回调
*/
const getResponse = ajax('tom/a','GET',{name:'xxx'},(res)=>{},(err)=>{})

解决方案

难道我要一个个改吗?既要更改传参,又要更改调用方式???这也太麻烦了。好在我知道适配器模式!开干!

// 更改旧的ajax方法
function ajax(url,method,params,success,fail){
    // 适配器函数登场
    AjaxAdapter(url,method,params,success,fail)
}
async AjaxAdapter(url,method,params,success,fail){
    let result = null
    if(method.toLowerCase() === 'get'){
        result = await HttpUtils.doGet(url)
    }else{
        result = await HttpUtils.doPost(url,params)
    }
    if(result && result.code === 200){
        // 假设成功的code为200
        success(result)
    }else{
        fail(result)
    }
}

如此一来,我只需要写一个适配器函数AjaxAdapter,就可以来保持新旧函数方法的统一了~