百度工程师教你玩转设计模式(适配器模式)
作者 | 北极星小组
在现实生活中,经常会遇到两个“对象” 因为接口不兼容而不能一起工作的场景,这时需要第三者进行适配,如:国内的充电线插头不一定适用国外的插座需要借助转接头、SD卡无法直接链接电脑需要借助读卡器、用直流电的笔记本电脑接交流电源时需要一个电源适配器等。
在软件设计中,需要开发的具有某种业务功能的组件在现有的组件库中已经存在,但它们与当前系统的接口规范不兼容,如果重新开发这些组件成本又很高,这时用适配器模式能很好地解决这些问题。
适配器模式(Adapter Pattern):是指将某个类的接口转化成客户端期望的另一个接口,主要目的是兼容性,让原本因接口不匹配不能工作的两个类可以协同工作。
△适配器示意图
适配器模式包含如下角色:
Target:目标抽象类, 定义客户要使用的接口
Adapter:适配器类,将Adaptee的接口进行适配转换
Adaptee:适配者类,需要被转换接口的对象
Client:客户类,通过适配器接口Target去使用Adaptee的功能
△对象适配器
△类适配器
一、适配器模式在文档业务场景中的应用(对象适配器)
微软office文档有两种数据格式,即office2007(OOXML格式)和Office2003(二进制格式)。在新业务场景中,因现有系统已经具备Office2007文档处理功能组件(数据、阅读器等),现在需要在此基础上扩充支持office2003格式的文档。即复用现有的office2007组件类,但接口与复用环境要求不一致,此时可以使用适配器模式。
示例使用对象适配器方式,忽略业务处理细节,仅做流程上的抽象来表明适配器模式的使用,根据模式结构抽象出各个角色类:
Doc2003目标抽象类
Doc2007适配者类
DocAdapter适配器类
Document客户类
// Document客户类使用方 public class Document { public void View(Doc2003 doc) { doc.show() } } // Doc2003接口抽象 public interface IDoc2003 { void show(); } // Doc2007适配者类 public class Doc2007 { public void show() { System.out.println("office2007标准处理流程"); } } // DocAdapter适配器类 public class DocAdapter implements IDoc2003 { private Doc2007 doc2007; public DocAdapter(Doc2007 doc2007){ this.doc2007 = doc2007; } @Override public void show() { System.out.println("适配器:这里省略了适配到2007的一堆适配逻辑..."); doc2007.show(); } } // 测试类 public class Test { public static void main(String[] args) { Document document = new Document(); Doc2003 doc2003 = new DocAdapter(new Doc2007()) ; document.view(doc2003); } }
二、适配器模式在替换依赖组件场景中的应用(类适配器)
在实际的研发过程中,我们经常会需要对依赖组件进行更新迭代。在替换时,相关调用代码,往往分布在非常多的地方,并且由于调用方法与参数不一致,逐个修改工作量大,且存在遗漏风险,这时候可以使用类适配器,将接口统一,减少相关代码的改动。
示例使用类适配器方式,忽略业务处理细节,仅做流程上的抽象来表明适配器模式的使用,根据模式结构抽象出各个角色类:
AHandler目标抽象类
BHandler适配者类
BAdapter适配器类
Client客户类
//原依赖库-目标抽象类 public class AHandler { public void operation() {} } //新依赖库-适配者类 public class BHandler { public void action() {} } //适配器类 public class BAdapter extends BHandler { public void operation() { ... super.action(); ... } } //客户类 public class Client { public static void main(String[] args) { //原调用 AHandler aHandler = new AHandler(); aHandler.operation(); //新调用 BAdapter bAdapter = new BAdapter(); bAdapter.operation(); } }
三、适配器模式在接口实现场景的应用(接口适配器)
在实际的开发过程中,一个接口有大量的方法,但是对应的不同类只需要关注部分方法,其他无关的方法全都实现过于繁琐,尤其是涉及的实现类过多的情况。
例如,现有一个需要的目标接口对象Target,定义了大量相关的方法。但是在实际使用过程只需分别关注其中部分方法,而不是全部实现。在此场景中:
被依赖的目标对象:TargetObj
适配器:Adapter
客户端:Client
// 目标对象:定义了大量的相关方法 public interface TargetObj { void operation1(); void operation2(); void operation3(); void operation4(); void operation5(); } // 适配器:将目标接口定义的方法全部做默认实现 public abstract class Adapter implements TargetObj { void operation1(){} void operation2(){} void operation3(){} void operation4(){} void operation5(){} } // 客户端:采用匿名内部类的方式实现需要的接口即可完成适配 public class Client { public static void main(String[] args) { Adapter adapter1 = new Adapter() { @Override public void operation3() { // 仅仅实现需要关注的方法即可 System.out.println("operation3") } } Adapter adapter2 = new Adapter() { @Override public void operation5() { // 仅仅实现需要关注的方法即可 System.out.println("operation5") } } adapter1.operation3(); adapter2.operation5(); } }
四、总结
以上介绍了三种使用适配器模式的场景,适配器模式本质上是将现有的不兼容的接口转换为需要的接口,不需要改变原来的代码结构即可实现新的功能,通常实现方式上有:
对象适配器:通过对象的组合来达到适配目的;
类适配器:通过类的继承或者接口的实现来达到适配目的;
接口适配器:通过实现接口的方式转换来达到适配的目的;
适配器模式是在现有的类和系统都不易修改的情况下使用,在系统设计之初慎用适配器模式,这样会导致代码可读性变差,不易维护。
---------- END ----------
推荐阅读【技术加油站】系列:

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Zadig 为什么能用的爽!(Zadig 企业案例第二期开篇)
作者:唐启涛,运维开发工程师 摘要:听听来自广州的 00 后工程师,讲述为什么 Zadig 用的爽?以及作为「过来人」的他,又是如何落地 Zadig,帮助提升工程师幸福度、帮助公司实现研发降本增效。 Who? 大家好,我叫唐启涛。目前就职于广州某公司,哈哈,刚刚入职没有多久,然后岗位应该算是运维还是运维开发,我也不知道。因为我工牌是运维开发,但是我企业微信又是运维,不过这个不重要,以下是我作为一个“Zadig 过来人”带来的一些使用分享、以及方案选型对比,希望对后续大家公司的 CI/CD 优化有所帮助。 传统 CI/CD 处理的问题 说到 CI/CD 的工具,IT 圈内名声最响亮的可能就会是传统的老牌 CI/CD 的王者之一:Jenkins。说到它基本上 IT 人都知道。在曾经云计算时代,乃至更久远的时代,因为那个时候软件架构还没有拆分成微服务,很多都是主机部署。所以 Jenkins 靠着一套 Pipeline 和自由风格流水线,打遍天下无敌手。 Jenkins 之所以能够这么纵横宇内有很大的一部分原因就是:开放,CI/CD,使用简单,能够走完一整套交付流程。 开放:意味着有着开放包容...
- 下一篇
十年磨一剑,veLinux深度解读
欢迎关注【字节跳动SYS Tech】。字节跳动SYS Tech 聚焦系统技术领域,与大家分享前沿技术动态、技术创新与实践、行业技术热点分析等内容。 veLinux简介 veLinux 是火山引擎推出的开源 Linux 操作系统,由字节跳动系统技术与工程团队主导研发,广泛集成了字节跳动多年来在支撑海量业务和亿级并发上的系统技术经验。致力于为用户提供稳定、高性能、安全、易用的 Linux 操作系统选择,提供全生命周期管理的完整解决方案和企业级服务支持。 自火山引擎开服以来,veLinux 支撑了包括容器服务、机器学习平台、大数据服务等大量公有云上业务,是火山引擎官方操作系统,为火山引擎各个云产品提供稳定的系统支撑,同时也服务了大量外部公有云客户,在不同的应用场景、不同的硬件机型上都表现出了优异的性能。 整体设计 veLinux 在整体设计上,兼容 x86 和 ARM 生态,同时兼容国内用户的使用习惯,并对多种硬件设备进行了适配和优化,同时针对火山引擎基础设施进行了深度优化: 向上提供更稳定、更安全、更易用的应用接口,并针对云原生、大数据、机器学习等场景提供针对性优化。 向下建立更准确、更完...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS7,CentOS8安装Elasticsearch6.8.6
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- CentOS7设置SWAP分区,小内存服务器的救世主
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Hadoop3单机部署,实现最简伪集群
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS8安装Docker,最新的服务器搭配容器使用
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- 2048小游戏-低调大师作品