前端的设计模式系列-适配器模式

发布时间 - 2025-07-21 00:00:00    点击率:

在学习和总结设计模式的过程中,确实有必要根据具体的编程语言来调整和理解这些模式。在javascript中,由于其基于原型的动态特性,设计模式的实现可能与传统的静态类型语言有所不同。以下是关于适配器模式的详细总结,按照您提出的“场景” - “设计模式定义” - “代码实现” - “更多场景” - “总”的顺序进行:

场景

在使用第三方库时,常常会遇到当前接口与第三方接口不匹配的情况。例如,使用一个Table组件,它要求返回的表格数据格式如下:

{
  code: 0, // 业务 code
  msg: '', // 出错时候的提示
  data: {
    total: , // 总数量
    list: [], // 表格列表
  }
};

但后端返回的数据格式可能是这样的:

{
  code: 0, // 业务 code
  message: '', // 出错时候的提示
  data: {
    total: , // 总数量
    records: [], // 表格列表
  }
};

此时,可以通过适配器模式进行数据格式的转换。

设计模式定义

维基百科对适配器模式的定义是:在不改变现有类的基础上,让它们能够正常使用另一个类。适配器模式在基于类的语言中有两种实现方式:

  1. 组合方式:适配器类内部包含原对象的实例。
  2. 继承方式:适配器类直接继承原类。

以下是UML类图的示例:

左边的Adapter内部拥有Adaptee的实例,右边的Adapter类直接继承Adaptee类。适配器会将AdapteespecificOperation方法进行相应的处理,包装为operation方法供client使用。

代码实现

在JavaScript中,我们可以使用函数来实现适配器模式。让我们用一个简单的例子来说明:现实生活中,iPhone有两种耳机插口,一种是Lightning,一种是传统的3.5毫米接口。如果是Lightning插口的耳机想要插到传统的3.5毫米接口的电脑上,就需要适配器。

首先,我们用Java来展示传统的适配器模式实现:

class Lightning耳机 {
    public void 插入Lighting接口() {
        System.out.println("插入到Lighting耳机接口成功");
    }
}

class 传统耳机 { public void 插入到传统耳机孔() { System.out.println("插入到传统耳机孔成功"); } }

class Lightning耳机到传统耳机适配器 extends 传统耳机 { public Lightning耳机 Lightning耳机;

public Lightning耳机到传统耳机适配器(Lightning耳机 耳机) {
    Lightning耳机 = 耳机;
}

public void 插入到传统耳机孔() {
    Lightning耳机.插入Lighting接口();
}

}

class 电脑传统耳机孔 { public 传统耳机 耳机;

public 电脑传统耳机孔(传统耳机 传统耳机) {
    耳机 = 传统耳机;
}

public void 插入耳机() {
    耳机.插入到传统耳机孔();
}

}

public class Main { public static void main(String[] args) { 传统耳机 传统耳机 = new 传统耳机(); 电脑传统耳机孔 电脑传统耳机孔 = new 电脑传统耳机孔(传统耳机); 电脑传统耳机孔.插入耳机(); // 插入到传统耳机孔成功

    Lightning耳机 Lightning耳机 = new Lightning耳机();
    电脑传统耳机孔 电脑传统耳机孔2 = new 电脑传统耳机孔(new Lightning耳机到传统耳机适配器(Lightning耳机));
    电脑传统耳机孔2.插入耳机(); // 插入到Lighting耳机接口成功
}

}

接下来,我们将其转换为JavaScript的实现:

const Lightning耳机 = {
插入Lighting接口() {
console.log("插入到Lighting耳机接口成功");
}
};

const 传统耳机 = { 插入到传统耳机孔() { console.log("插入到传统耳机孔成功"); } };

const 电脑传统耳机孔 = { 插入耳机(耳机) { 耳机.插入到传统耳机孔(); } };

const Lightning耳机到传统耳机适配器 = function(Lightning耳机) { return { 插入到传统耳机孔() { Lightning耳机.插入Lighting接口(); } }; };

电脑传统耳机孔.插入耳机(传统耳机); // 插入到传统耳机孔成功 电脑传统耳机孔.插入耳机(Lightning耳机到传统耳机适配器(Lightning耳机)); // 插入到Lighting耳机接口成功

回到开头的问题,Table组件提供了一个responseProcessor的钩子,我们可以通过这个钩子将接口返回的数据进行包装:

{
...
responseProcessor(res) {
return {
...res,
msg: res.message, // 出错时候的提示
data: {
...res.data,
list: res?.data?.records || [], // 表格列表
}
};
},
...
}

更多场景

除了应对数据格式不一致的问题,适配器模式还可以为上层提供统一接口,解决兼容性问题。一个典型的例子是jQuery,它通过适配器模式来处理不同浏览器的兼容性问题。例如:

// Create the request object
// (This is still attached to ajaxSettings for backward compatibility)
jQuery.ajaxSettings.xhr = window.ActiveXObject !== undefined ?
// Support: IE6-IE8
function() {
// XHR cannot access local files, always use ActiveX for that case
if (this.isLocal) {
return createActiveXHR();
}
// Support: IE 9-11
// IE seems to error on cross-domain PATCH requests when ActiveX XHR
// is used. In IE 9+ always use the native XHR.
// Note: this condition won't catch Edge as it doesn't define
// document.documentMode but it also doesn't support ActiveX so it won't
// reach this code.
if (document.documentMode > 8) {
return createStandardXHR();
}
// Support: IE
} :
createStandardXHR;

适配器模式是一种相对简单的设计模式,在JavaScript中可以通过函数进行转换。适配器模式和代理模式在代码结构上相似,但它们的意图不同:适配器模式是为了解决两个对象之间不匹配的问题,而代理模式是为了增强原对象的功能,提供的接口不会改变。

通过学习和总结适配器模式,我们可以更好地理解如何在JavaScript中应用设计模式,以解决实际开发中的问题。


# linux  # 浏览器  # 电脑  # access  # iphone  # ai  # 变现  # Java  # JavaScript  # jquery  # Static  # String  # void  # 继承  # 接口  # class  # public  # 对象  # table  # uml  # 数据格式  # 我们可以  # 可以通过  # 第三方  # 是为了  # 不匹配  # 是一种  # 让我们  # 是这样  # 基础上 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: JS中使用new Date(str)创建时间对象不兼容firefox和ie的解决方法(两种)  香港服务器网站搭建教程-电商部署、配置优化与安全稳定指南  如何将凡科建站内容保存为本地文件?  Laravel如何使用Eloquent进行子查询  Laravel如何升级到最新版本?(升级指南和步骤)  Laravel如何使用Socialite实现第三方登录?(微信/GitHub示例)  如何解决hover在ie6中的兼容性问题  如何用PHP工具快速搭建高效网站?  laravel怎么实现图片的压缩和裁剪_laravel图片压缩与裁剪方法  高性能网站服务器部署指南:稳定运行与安全配置优化方案  Laravel中DTO是什么概念_在Laravel项目中使用数据传输对象(DTO)  如何在阿里云虚拟服务器快速搭建网站?  Laravel如何使用Passport实现OAuth2?(完整配置步骤)  php json中文编码为null的解决办法  高端建站如何打造兼具美学与转化的品牌官网?  软银砸40亿美元收购DigitalBridge 强化AI资料中心布局  Win10如何卸载预装Edge扩展_Win10卸载Edge扩展教程【方法】  ChatGPT常用指令模板大全 新手快速上手的万能Prompt合集  如何在企业微信快速生成手机电脑官网?  香港服务器网站推广:SEO优化与外贸独立站搭建策略  高防服务器:AI智能防御DDoS攻击与数据安全保障  Laravel如何处理表单验证?(Requests代码示例)  如何自定义safari浏览器工具栏?个性化设置safari浏览器界面教程【技巧】  Laravel怎么为数据库表字段添加索引以优化查询  Laravel的契約(Contracts)是什么_深入理解Laravel Contracts与依赖倒置  Laravel如何将应用部署到生产服务器_Laravel生产环境部署流程  JavaScript常见的五种数组去重的方式  香港代理服务器配置指南:高匿IP选择、跨境加速与SEO优化技巧  如何在阿里云虚拟主机上快速搭建个人网站?  Win11关机界面怎么改_Win11自定义关机画面设置【工具】  Laravel怎么调用外部API_Laravel Http Client客户端使用  Laravel用户密码怎么加密_Laravel Hash门面使用教程  如何使用 Go 正则表达式精准提取括号内首个纯字母标识符(忽略数字与嵌套)  Laravel如何为API生成Swagger或OpenAPI文档  Edge浏览器提示“由你的组织管理”怎么解决_去除浏览器托管提示【修复】  百度浏览器ai对话怎么关 百度浏览器ai聊天窗口隐藏  Java遍历集合的三种方式  javascript读取文本节点方法小结  悟空识字怎么关闭自动续费_悟空识字取消会员自动扣费步骤  Laravel怎么使用Collection集合方法_Laravel数组操作高级函数pluck与map【手册】  儿童网站界面设计图片,中国少年儿童教育网站-怎么去注册?  如何在 Python 中将列表项按字母顺序编号(a.、b.、c. …)  如何挑选高效建站主机与优质域名?  Laravel如何创建自定义Artisan命令?(代码示例)  如何快速搭建高效简练网站?  企业在线网站设计制作流程,想建设一个属于自己的企业网站,该如何去做?  nodejs redis 发布订阅机制封装实现方法及实例代码  如何快速建站并高效导出源代码?  如何用免费手机建站系统零基础打造专业网站?  详解ASP.NET 生成二维码实例(采用ThoughtWorks.QRCode和QrCode.Net两种方式)