javascript 设计模式之适配器模式

文章系列

javascript 设计模式之单例模式javascript

javascript 设计模式之适配器模式java

javascript 设计模式之装饰者模式git

javascript设计模式之代理模式github

javascript 适配、代理、装饰者模式的比较web

javascript 设计模式之状态模式json

javascript 设计模式之迭代器模式设计模式

javascript 设计模式之策略模式浏览器

javascript 设计模式之观察者模式markdown

javascript 设计模式之发布订阅者模式网络

概念

适配器模式:将一个类(对象)的接口(方法或属性)转化成客户但愿的另一个接口(方法或属性),使得本来因为接口不兼容而不能一块儿工做的那些类(对象)能够正常协做。简单理解就是为兼容而生的 “转换器”。

本文代码

生活中的适配器

好比生活中去香港或国外,电源接口跟国内不一样就须要一个转换器 电源转换器 再好比Type-c 转接口,我以前用的耳机线都是圆头的,直到最近买了个小米10 手机,发现它的手机孔居然是方形的,好在厂商有送了个转换器,我才能继续听歌 耳机转换器

比照上面的定义,

  • 类:小米10
  • 类的接口:方形
  • 客户(我)
  • 另外一种接口:圆形

适配器的业务场景

插头转换器

class Adapter {
	specificRequest() {
		return '德国标准插头'
	}
}
class Target {
	constructor() {
		this.adapter = new Adapter()
	}
	request() {
		let info = `${this.adapter.specificRequest()}---转换成---中国插头`
		return info
	}
}
let target = new Target()
console.info(target.request())

复制代码

地图接口之间的适配

var googleMap = {
	show: function () {
		// 方法是show
		console.log('开始渲染谷歌地图')
	}
}
var baiduMap = {
	display: function () {
		//方法是display
		console.log('开始渲染百度地图')
	}
}
var baiduMapAdapter = {
	show: function () {
		//适配器也改成show,返回的是display
		return baiduMap.display()
	}
}
//下面是渲染地图的方法,传入地图对象
var renderMap = function (map) {
	//传入地图对象
	if (map.show instanceof Function) {
		//判断
		map.show() //地图对象的show方法
		//在传入baiduMapAdapter对象的时候,调用show方法,返回的
		//实际是baiduMap的display方法。
	}
}

renderMap(googleMap) // 输出:开始渲染谷歌地图
renderMap(baiduMapAdapter) // 输出:开始渲染百度地图

复制代码

兼容接口请求

export default class HttpUtils {
  // get方法
  static get(url) {
    return new Promise((resolve, reject) => {
      // 调用fetch
      fetch(url)
        .then(response => response.json())
        .then(result => {
          resolve(result)
        })
        .catch(error => {
          reject(error)
        })
    })
  }
  
  // post方法,data以object形式传入
  static post(url, data) {
    return new Promise((resolve, reject) => {
      // 调用fetch
      fetch(url, {
        method: 'POST',
        headers: {
          Accept: 'application/json',
          'Content-Type': 'application/x-www-form-urlencoded'
        },
        // 将object类型的数据格式化为合法的body参数
        body: this.changeData(data)
      })
        .then(response => response.json())
        .then(result => {
          resolve(result)
        })
        .catch(error => {
          reject(error)
        })
    })
  }
  
  // body请求体的格式化方法
  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
  }
}
复制代码

当想使用fetch 发起请求时,只须要按以下方式调用便可:

// 定义目标url地址
const URL = "xxxxx"
// 定义post入参
const params = {
    ...
}

// 发起post请求
 const postResponse = await HttpUtils.post(URL,params) || {}
 
 // 发起get请求
 const getResponse = await HttpUtils.get(URL)
复制代码

但项目中难免有些旧的接口调用方式,好比有以下的:

// 发送get请求
Ajax('get', url地址, post入参, function(data){
    // 成功的回调逻辑
}, function(error){
    // 失败的回调逻辑
})

复制代码

为了抹平差别,能够采用适配器模式

// Ajax适配器函数,入参与旧接口保持一致
async function AjaxAdapter(type, url, data, success, failed) {
    const type = type.toUpperCase()
    let result
    try {
         // 实际的请求所有由新接口发起
         if(type === 'GET') {
            result = await HttpUtils.get(url) || {}
        } else if(type === 'POST') {
            result = await HttpUtils.post(url, data) || {}
        }
        // 假设请求成功对应的状态码是1
        result.statusCode === 1 && success ? success(result) : failed(result.statusCode)
    } catch(error) {
        // 捕捉网络错误
        if(failed){
            failed(error.statusCode);
        }
    }
}

// 用适配器适配旧的Ajax方法
async function Ajax(type, url, data, success, failed) {
    await AjaxAdapter(type, url, data, success, failed)
}
复制代码

如此一来,就用适配器 (AjaxAdapter) 去承接旧接口的参数,实现新旧接口的无缝对接。

使用适配器模式的场景

jQuery 中的应用

适配器模式很是适用于跨浏览器兼容,例如强大的 jQuery 封装了事件处理的适配器,解决跨浏览器兼容性问题。

// $('selector').on 的实现
function on(target, event, callback) {
    if (target.addEventListener) {
        // 标准事件监听
        target.addEventListener(event, callback);
    } else if (target.attachEvent) {
        // IE低版本事件监听
        target.attachEvent(event, callback)
    } else {
        // 低版本浏览器事件监听
        target[`on${event}`] = callback
    }
}
复制代码

参考连接

JavaScript 设计模式核⼼原理与应⽤实践

结语

你的点赞是对我最大的确定,若是以为有帮助,请留下你的赞扬,谢谢!!!