适配器模式(Adapter Pattern)又称包装器模式,将一个类(对象)的接口(方法、属性)转化为用户需要的另一个接口,解决类(对象)之间接口不兼容的问题。
主要功能是进行转换匹配,目的是复用已有的功能,而不是来实现新的接口。也就是说,访问者需要的功能应该是已经实现好了的,不需要适配器模式来实现,适配器模式主要是负责把不兼容的接口转换成访问者期望的格式而已。
现实生活中我们会遇到形形色色的适配器,最常见的就是转接头了,比如不同规格电源接口的转接头、iPhone 手机的 3.5 毫米耳机插口转接头、DP/miniDP/HDMI/DVI/VGA 等视频转接头、电脑、手机、ipad 的电源适配器,都是属于适配器的范畴。
在类似场景中,这些例子有以下特点:
电源适配器的例子,一开始我们使用的中国插头标准:
但是我们出国旅游了,到了日本,需要增加一个日本插头到中国插头的电源适配器,来将我们原来的电源线用起来:
访问者需要目标对象的某个功能,但是这个对象的接口不是自己期望的,那么通过适配器模式对现有对象的接口进行包装,来获得自己需要的接口格式。
var chinaPlug = { name: ‘china plug‘, chinaPlug() { console.log(this.name); } } var japanPlug = { name: ‘japan plug‘, japanPlug() { console.log(this.name); } } function japanPlugAdapter(plug) { return { // 改变chinaPlug调用接口,不影响之前的调用接口 chinaPlug() { return plug.japanPlug() } } } chinaPlug.chinaPlug() japanPlugAdapter(japanPlug).chinaPlug()
有的使用 jQuery 的老项目使用 $.ajax
来发送请求,现在的新项目一般使用 Axios,那么现在有个老项目的代码中全是 $.ajax
,如果你挨个修改,那么 bug 可能就跟地鼠一样到处冒出来让你焦头烂额,这时可以采用适配器模式来将老的使用形式适配到新的技术栈上。
/* 适配器 */ function ajax2AxiosAdapter(ajaxOptions) { return axios({ url: ajaxOptions.url, method: ajaxOptions.type, responseType: ajaxOptions.dataType, data: ajaxOptions.data }) .then(ajaxOptions.success) .catch(ajaxOptions.error) } /* 经过适配器包装 */ $.ajax = function(options) { return ajax2AxiosAdapter(options) } $.ajax({ url: ‘/demo-url‘, type: ‘POST‘, dataType: ‘json‘, data: { name: ‘张三‘, id: ‘2345‘ }, success: function(data) { console.log(‘访问成功!‘) }, error: function(err) { console.err(‘访问失败~‘) } })
增加适配器后,就可以将原先状态的树形结构转化为所需的结构,而并不改动原先的数据,也不对原来使用旧数据结构的代码有所影响。
/* 树形结构平铺 */ function treeDataAdapter(treeData, lastArrayData = []) { treeData.forEach(item => { if (item.children) { treeDataAdapter(item.children, lastArrayData) } const { name, place } = item lastArrayData.push({ name, place }) }) return lastArrayData } // 返回平铺的组织结构 console.log("newData:", treeDataAdapter(oldTreeData)) console.log("oldData:", oldTreeData);
旧有 data 中的数据不满足当前的要求,通过计算属性的规则来适配成我们需要的格式,对原有数据并没有改变,只改变了原有数据的表现形式。
<template> <div id="example"> <p>Original message: "{{ message }}"</p> <!-- Hello --> <p>Computed reversed message: "{{ reversedMessage }}"</p> <!-- olleH --> </div> </template> <script type=‘text/javascript‘> export default { name: ‘demo‘, data() { return { message: ‘Hello‘ } }, computed: { reversedMessage: function() { return this.message.split(‘‘).reverse().join(‘‘) } } } </script>
适配器模式的优点:
适配器模式的缺点:会让系统变得零乱,明明调用 A,却被适配到了 B,如果系统中这样的情况很多,那么对可阅读性不太友好。如果没必要使用适配器模式的话,可以考虑重构,如果使用的话,可以考虑尽量把文档完善。
原文:https://www.cnblogs.com/Nyan-Workflow-FC/p/13053455.html