欢迎大家来到IT世界,在知识的湖畔探索吧!
本篇讲解Java设计模式中的单例模式,分为定义、模式应用前案例、结构、模式应用后案例、适用场景、模式可能存在的困惑和本质探讨7个部分。
定义
适配器模式指的是将一个类的接口转换成客户希望的另一个接口。该模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
在新的分类方式中,适配器模式被划分至类行为相关需求类别中,其应对的是原有类的行为不满足标准接口的情形。
模式应用前案例
此处列举一个银行领域数据交换的案例。在一些年代建设较早的银行系统中,银行经常会制定自身的数据格式。
然而,如果涉及到跨行之间的一些交换,那么就只能按照银联或人行规定的数据交换格式来进行。在这种情形下,为了尽可能少的修改存量代码,就会使用适配器模式。
首先,我们先来看一下未使用适配器模式之前的代码实现以及存在的主要问题。
public class ConcreteBankSystem {//某一具体银行系统(Adaptee)- 使用该银行特定格式的数据 public void sendConcreteBankData(String bankData) { System.out.println("Sending Concrete Bank data: " + bankData); } } public class Client {// 客户端代码直接处理数据格式转换并调用发送方法 public static void main(String[] args) { // 创建一家新客户资料 String newClientData = "Name:Sun, Account Number:12345"; // 格式化为某一具体银行特定HTML格式 String formattedData = "<concreteBank-data>" + newClientData + "</concreteBank-data>"; // 初始化一个某一具体银行系统对象 ConcreteBankSystem bankSystem =new ConcreteBankSystem(); // 直接调用某一具体银行系统的发送方法 bankSystem.sendConcreteBankData(formattedData); } }
欢迎大家来到IT世界,在知识的湖畔探索吧!
在上面案例中,如果需要给某个具体银行发送报文,由于该银行未使用标准格式,因此需要将报文转换之后,再调用具体接口进行发送。
如果存在其他的银行也未使用标准格式,那么每一个银行均需要做定制化转换工作。这样方式下,调用方代码与具体的实现代码紧耦合,并且后续如果某一具体银行修改成标准接口或者其他格式,调用方也需要一并修改。
结构
适配器模式的示例代码如下。
欢迎大家来到IT世界,在知识的湖畔探索吧!public interface Target { void request(); } public class Adaptee { public void specificRequest() { System.out.println("Called specificRequest()"); } } public class Adapter implements Target { private Adaptee adaptee; public Adapter(Adaptee adaptee) { this.adaptee = adaptee; } @Override public void request() { adaptee.specificRequest(); } } public class Client { public static void main(String[] args) { // 创建需要被适配的对象 Adaptee adaptee = new Adaptee(); // 创建适配器对象,传入需要被适配的对象 Target target = new Adapter(adaptee); // 通过适配器对象调用request()方法,适配器会将此方法转换为对Adaptee类中specificRequest()方法的调用 target.request(); } }
模式应用后案例
上述银行数据交换的案例,使用适配器模式之后的代码如下所示。
某一具体银行系统的数据发送接口以及银联或人行要求的标准的接口。
public class ConcreteBankSystem {//某一具体银行系统(Adaptee)- 使用某一具体银行特定格式的数据 public void sendConcreteBankData(String bankData) { System.out.println("Sending Concrete Bank data: " + bankData); } } public interface IBankDataExchangeService {// 目标接口(Target)- 银行数据交换服务 void sendData(String data); }
适配器类,将某一银行具体接口转换为标准规范接口。
欢迎大家来到IT世界,在知识的湖畔探索吧!public class ConcreteBankAdapter implements IBankDataExchangeService{// 适配器类(Adapter),将某一具体银行系统转换为目标接口 BankDataExchangeService private final ConcreteBankSystem bankSystem = new ConcreteBankSystem(); @Override public void sendData(String data) { //转换成某一具体银行系统可识别的格式并发送数据 String formattedData = this.formatToConcreteBankHtml(data); this.bankSystem.sendConcreteBankData(formattedData); } //格式化为某一具体银行特定HTML格式 private String formatToConcreteBankHtml(String data){ return "<concreteBank-data>" + data + "</concreteBank-data>"; } }
最后,调用方代码如下。
public class Client {//调用方代码 public static void main(String args[]) { // 创键一家新客户资料 String newClientData= "Name:Sun, Account Number:12345"; // 使用适配者模式创建一个符合目标接口adapter对象 IBankDataExchangeService adapter = new ConcreteBankAdapter(); //调用sendData方法 实际上会调用ConcreteBankSystem中sendConcreteBankData方法 adapter.sendData(newClientData); } }
适用场景
适配器模式使用的场景包括以下这些:
1、想使用一个已经存在的类,而它的接口不符合需求。可能是由于之前设计过早未考虑标准化、设计存在缺陷或是外部厂商的系统等
2、存在多个版本的接口,希望有一个接口兼容老版本的接口
3、统一已经存在的多个类的接口,例如Slf4j日志框架即是如此
模式可能存在的困惑
困惑1:适配器模式有两种实现方式:类适配器和对象适配器,两者有什么区别?
适配器模式中,Adapter类中需要调用被适配类Adaptee的接口,所以两者之间需要产生交互关系。在面向对象中,主要可以通过继承和组合两种方式实现。
其中,通过继承关系实现就是类适配器方式,通过组合关系实现则为对象适配器方式。在上述6.4的案例中,采用的是对象适配器方式。
由于笔者倾向于继承体现的是现实中概念之间的层次关系,因此只有类体现了现实中这种层次关系时,才建议使用继承方式。
本质
适配器的本质是用于应对原有类的行为不满足特定的需求。但是值得注意的是,这种不满足的情形指的并不是功能上需要增强,类似于后续代理模式或装饰者模式等,而仅仅是行为的对外暴露接口需要转换成另一种形式。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/73078.html