1.简介1.1定义适配器模式(AdapterPattern),又称包装器模式,将一个类(对象)的接口(方法、属性)转换为用户需要的另一个接口,解决类(对象)之间接口不兼容的问题.旧界面与用户不兼容。中间添加适配器,转换接口1.2主要功能主要功能是进行转换和匹配,目的是复用现有功能,而不是实现新的接口。也就是说,访问者需要的功能应该已经实现了,不需要适配器模式来实现。适配器模式主要负责将不兼容的接口转换成访问者期望的格式。2.生活中的例子电源接口适配器、Type-C转HDMI等视频适配器。同声传译,充当两国友人之间的中介在类似的场景下,这些例子有以下特点:旧的界面格式已经不能满足现在的需求。通过添加适配器更好地使用遗留接口。3.一般实现3.1作用Target:TargetabstractclassAdapter:AdapterclassAdaptee:AdapterclassClient:Clientclass3.2CodeclassSocket{output(){return'output220V';}}abstractclassPower{abstractcharge():string;}classPowerAdapterextendsPower{constructor(publicsocket:Socket){super();}//转换后和转换前的界面不同charge(){returnthis.socket.output()+'}}letpowerAdapter=newPowerAdapter(newSocket());console.log(powerAdapter.charge());4。场景当你想使用已有对象的功能,但又想修改它使用接口时,一般可以考虑是否可以应用适配器模式。如果你想使用一个已有的对象,但它的接口不符合要求,你可以使用适配器模式,将已有的实现转换成你需要的接口。如果你想创建一个可重用的对象,并且你确定你需要使用一些不兼容的对象,你可以在这种情况下使用适配器模式,然后适配你需要的东西。4.1axiosAxiosdispatchRequestAxios源码使用process和XMLHttpRequest。通过宿主环境特有对象识别当前环境,适应不同环境如:客户端浏览器、nodejs请求方式。defaults/adapters目录包含以下文件├─adapters│http.js│README.md│xhr.jsxhrhttpadapter的入参都是config,返回都是promises//letaxios=require('axios');leturl=require('url');functionaxios(config:any):any{letadapter=getDefaultAdapter();returnadapter(config);}axios({method:'GET',url:'http://localhost:8080/api/user?id=1'}).then(function(response:any){console.log(响应);},function(error:any){console.log(error);})functionxhr(config:any){returnnewPromise(function(resolve,reject){varrequest=newXMLHttpRequest();request.open(config.method,config.url,true);request.onreadystatechange=function(){if(request.readyState==4){if(request.status==200){resolve(request.response);}else{reject('请求失败');}}}})}functionhttp(config:any){lethttp=require('hHTTP');让urlObject=url.parse(config.url);returnnewPromise(function(resolve,reject){constoptions={hostname:urlObject.hostname,port:urlObject.port,path:urlObject.pathname,method:config.method};varreq=http.request(选项,函数(res:any){letchunks:any[]=[];res.on('data',(chunk:any)=>{chunks.push(chunk);});res.on('end',(){resolve(Buffer.concat(chunks).toString());});});req.on('error',(err:any)=>{reject(err);});req.end();})}functiongetDefaultAdapter():any{varadapter;if(typeofXMLHttpRequest!=='undefined'){adapter=xhr;}elseif(typeofprocess!=='undefined'){adapter=http;}返回适配器;}server.jsletexpress=require('express');letapp=express();app.get('/api/user',(req,res)=>{res.json({id:req.query.id,name:'竹峰'});});app.listen(8080);4.2jQuery.ajax适配Axios一些老项目用jQuery用$.ajax发送请求,现在新项目普遍使用Axios,所以现在有一个老项目代码全是$.ajax,如果你一个一个修改,工作量无疑是巨大的,而且很容易造成各种乱七八糟的bug。这时候可以使用adapter模式,让旧的使用形式适应新的技术栈:/*Adapter*/functionajax2AxiosAdapter(ajaxOptions){returnaxios({url:ajaxOptions.url,method:ajaxOptions.type,responseType:ajaxOptions.dataType,data:ajaxOptions.data}).then(ajaxOptions.success).catch(ajaxOptions.error)}/*由适配器包裹*/$.ajax=function(options){returnajax2AxiosAdapter(options);}//测试:在jQuery中发送Ajax请求$.ajax({url:'/demo-url',type:'POST',dataType:'json',data:{name:'张三',id:'13'},success:function(data){console.log('请求成功!')},error:function(err){console.error('请求失败!')}})可以看到老的代码不变,但真正的请求是通过新的发送方式发送的。当然,你也可以将Axios请求适配为$.ajax,这取决于你如何使用适配器。4.3promisify函数:将回调形式转化为Promise对象Node中的异步回调有一个约定:Error优先,回调函数中第一个参数必须是Error对象,其余参数为正确的数据.letfs=require('fs');varBluebird=require("bluebird");letreadFile=Bluebird.promisify(fs.readFile);(asyncfunction(){letcontent=awaitreadFile('./1.txt','utf8');console.log(content);})()functionpromisify(readFile:any){returnfunction(filename:any,encoding:any){returnnewPromise(function(resolve,reject){readFile(文件名,编码,函数(错误:任何,数据:任何){如果(错误)拒绝(错误);否则解决(数据);})});}}4.4业务数据适配在实际项目中,我们经常会遇到树型数据结构和表型数据结构的转换,比如国家省市结构、公司组织结构、军编制结构等。以公司的组织结构为例。在历史代码中,后台提供了公司组织结构的树状数据。在以后的业务迭代中,会增加一些需要非树结构的场景。比如增加了维护组织的功能,所以在添加组织的时候需要选择上级组织,在下拉菜单中选择新添加组织的上级菜单。或者添加需要分配人员到某个级别的组织,你需要在下拉菜单中选择任何级别的组织。在这些业务场景中,需要对树结构进行扁平化处理,但是我们不能直接修改旧的树结构状态,因为旧的树结构状态已经在项目的其他地方使用了。这时候我们可以引入一个适配器来适配旧的数据结构:/*原始树结构*/constoldTreeData=[{name:'总部',place:'一楼',children:[{name:'财务部',place:'二楼'},{name:'生产部',place:'三楼'},{name:'开发部',place:'三楼',children:[{name:'软件部',place:'四楼',children:[{name:'后端',place:'五楼'},{name:'前端',place:'七楼'},{name:'技术支持部',place:'六楼'}]},{name:'硬件部',place:'四楼',children:[{name:'DSP部',place:'八楼'},{name:'ARM部门',place:'二楼'},{name:'调试部',place:'三楼'}]}]}]}]/*树结构平铺*/functiontreeDataAdapter(treeData,lastArrayData=[]){treeData.forEach(item{if(item.children){treeDataAdapter(item.children,lastArrayData)}const{name,place}=itemlastArrayData.push({name,place})})复制代码returnlastArrayData}//测试:返回分片组织结构treeDataAdapter(oldTreeData)添加适配器后,可以在不改变原始数据或使用旧数据结构的代码的情况下,将原始状态的树结构转换为需要的结构被影响。4.5Vue计算属性Vue中的计算属性也是适配器模式的一个实例。以官网的例子为例,大家一起来理解:-->
计算的反向消息:“{{reversedMessage}}”