设计模式-适配器模式
适配器模式又称为包装器模式,将一个类的接口转化为用户需要的另外一个接口,主要是为了解决对象之间接口不兼容的问题,比如随着业务迭代升级出现了旧的接口与心的接口不兼容,这个时候不可能强制使用旧接口的用户去升级,而是在中间加一个适配器进行转换,让旧接口的使用者无感使用,保证了稳定性,在日常生活中适配器的案例随处可见,比如耳机插口不统一、充电接口不统一等,这个时候就需要一个适配器来解决问题
UML:
接下看一下UML对应的代码实现:
class Target { constructor(type) { let result; switch (type) { case "adapter": result = new Adapter(); break; default: result = null; } return result; } Request() { console.log('Target Request'); } } class Adaptee { constructor() { console.log("Adaptee created"); } SpecificRequest() { console.log("Adaptee request"); } } class Adapter extends Adaptee { constructor() { super(); console.log("Adapter created"); } Request() { return this.SpecificRequest(); } } function init_Adapter() { var f = new Target("adapter"); f.Request(); } init_Adapter(); 复制代码
应用场景
开发中常用的axios,其支持node端和浏览器端,那么在不同端调用axios需要进行不同的处理,而这些对于使用者而言都是无感的,我们在使用的时候都是使用同一套API直接干就完事了,不会在意内部具体做了些什么,这个时候就需要使用适配器来抹平不同端的差异,让使用者用着开心
接下来可以模拟简单实现这个过程
使用axios请求一个接口:
axios({ url: "xxx", method: "GET", }) .then((res) => { console.log("success:", res); }) .catch((err) => { console.log("fail:", err); }); 复制代码
接下来需要手动实现axios函数:
function axios(config) { let adaptor = getDefaultAdaptor(); // 无论是node端 还是 浏览器端,在使用的时候都只是转入一个config配置对象,返回一个 Promise 对象 return adaptor(config); } 复制代码
上文说到因为axios可以在浏览器端和node端使用,getDefaultAdaptor函数就是起到适配器的作用,根据不同的环境分别创建不同的adaptor
/** * 适配器 */ function getDefaultAdaptor() { let adaptor; if (typeof XMLHttpRequest !== "undefined") { // 是浏览器环境 adaptor = xhr; } else if (typeof process !== "undefined") { // node 环境 adaptor = http; } return adaptor; } 复制代码
其中xhr和http为两个函数,用于创建具体的请求,至此适配器的使用已经完成,接下来就看看不同端是如何实现的接口请求
浏览器端:
/** * 浏览器环境 */ function xhr(config) { return new Promise((resolve, reject) => { const req = new XMLHttpRequest(); req.open(config.method, config.url, true); req.onreadystatechange = function () { if (req.readyState === 4) { if (req.status >= 200 && req.status < 300) { resolve(req.responseText); } else { reject("请求失败"); } } }; req.send(); }); } 复制代码
node端:
/** * node 环境 */ function http(config) { const url = require("url"); const http = require("http"); // 将需要的参数 解析出来 const { hostname, port, path } = url.parse(config.url); return new Promise((resolve, reject) => { const options = { hostname, port, path, method: config.method, }; const req = http.request(options, function (response) { let chunks = []; response.on("data", (chunk) => { chunks.push(chunk); }); response.on("end", () => { const res = Buffer.concat(chunks).toString(); resolve(res); }); }); // 监听请求异常 req.on("error", (err) => { reject(err); }); // 请求发送完毕 ren.end(); }); }
作者:Nordon
链接:https://juejin.cn/post/7016215674322157581