4.2 解决方案
4.2.1 适配器模式来解决
用来解决上述问题的一个合理的解决方案就是适配器模式。那么什么是适配器模式呢?
(1)适配器模式定义
(2)应用适配器模式来解决的思路
仔细分析上面的问题,问题的根源在于接口的不兼容,功能是基本实现了的,也就是说,只要想办法让两边的接口匹配起来,就可以复用第一版的功能了。
按照适配器模式的实现方式,可以定义一个类来实现第二版的接口,然后在内部实现的时候,转调第一版已经实现了的功能,这样就可以通过对象组合的方式,既复用了第一版已有的功能,同时又在接口上满足了第二版调用的要求。
完成上述工作的这个类就是适配器。
4.2.2 模式结构和说明
适配器模式的结构如图4.6所示:
图4.6 适配器模式结构图
Client:
客户端,调用自己需要的领域接口Target。
Target:
定义客户端需要的跟特定领域相关的接口。
Adaptee:
已经存在的接口,通常能满足客户端的功能要求,但是接口与客户端要求的特定领域接口不一致,需要被适配。
Adapter:
适配器,把Adaptee适配成为Client需要的Target。
4.2.3 适配器模式示例代码
(1)先看看Target接口的定义,示例代码如下:
/** * 定义客户端使用的接口,与特定领域相关 */ public interface Target { /** * 示意方法,客户端请求处理的方法 */ public void request(); } |
(2)再看看需要被适配的对象定义,示例代码如下:
/** * 已经存在的接口,这个接口需要被适配 */ public class Adaptee { /** * 示意方法,原本已经存在,已经实现的方法 */ public void specificRequest() { //具体的功能处理 } } |
(3)再看看适配器对象的基本实现,示例代码如下:
/** * 适配器 */ public class Adapter implements Target { /** * 持有需要被适配的接口对象 */ private Adaptee adaptee; /** * 构造方法,传入需要被适配的对象 * @param adaptee 需要被适配的对象 */ public Adapter(Adaptee adaptee) { this.adaptee = adaptee; }
public void request() { //可能转调已经实现了的方法,进行适配 adaptee.specificRequest(); } } |
(4)再来看看使用适配器的客户端,示例代码如下:
/** * 使用适配器的客户端 */ public class Client { public static void main(String[] args) { //创建需被适配的对象 Adaptee adaptee = new Adaptee(); //创建客户端需要调用的接口对象 Target target = new Adapter(adaptee); //请求处理 target.request(); } } |
4.2.4 使用适配器模式来实现示例
要使用适配器模式来实现示例,关键就是要实现这个适配器对象,它需要实现第二版的接口,但是在内部实现的时候,需要调用第一版已经实现的功能。也就是说,第二版的接口就相当于适配器模式中的Target接口,而第一版已有的实现就相当于适配器模式中的Adaptee对象。
(1)把这个适配器简单的实现出来,示意一下,示例代码如下:
/** * 适配器对象,把记录日志到文件的功能适配成第二版需要的增删改查的功能 */ public class Adapter implements LogDbOperateApi{ /** * 持有需要被适配的接口对象 */ private LogFileOperateApi adaptee; /** * 构造方法,传入需要被适配的对象 * @param adaptee 需要被适配的对象 */ public Adapter(LogFileOperateApi adaptee) { this.adaptee = adaptee; }
public void createLog(LogModel lm) { //1:先读取文件的内容 List<LogModel> list = adaptee.readLogFile(); //2:加入新的日志对象 list.add(lm); //3:重新写入文件 adaptee.writeLogFile(list); } public List<LogModel> getAllLog() { return adaptee.readLogFile(); } public void removeLog(LogModel lm) { //1:先读取文件的内容 List<LogModel> list = adaptee.readLogFile(); //2:删除相应的日志对象 list.remove(lm); //3:重新写入文件 adaptee.writeLogFile(list); } public void updateLog(LogModel lm) { //1:先读取文件的内容 List<LogModel> list = adaptee.readLogFile(); //2:修改相应的日志对象 for(int i=0;i<list.size();i++){ if(list.get(i).getLogId().equals(lm.getLogId())){ list.set(i, lm); break; } } //3:重新写入文件 adaptee.writeLogFile(list); } } |
(2)此时的客户端也需要一些改变,示例代码如下:
public class Client { public static void main(String[] args) { //准备日志内容,也就是测试的数据 LogModel lm1 = new LogModel(); lm1.setLogId("001"); lm1.setOperateUser("admin"); lm1.setOperateTime("2010-03-0210:08:18"); lm1.setLogContent("这是一个测试"); List<LogModel> list = new ArrayList<LogModel>(); list.add(lm1); //创建操作日志文件的对象 LogFileOperateApi logFileApi = new LogFileOperate("");
//创建新版的操作日志的接口对象 LogDbOperateApi api = new Adapter(logFileApi);
//保存日志文件 api.createLog(lm1); //读取日志文件的内容 List<LogModel> allLog = api.getAllLog(); System.out.println("allLog="+allLog); } } |
去运行一下,测试看看是否能满足要求。
(3)小结一下思路
在看完前面的思路和范例代码后,来对这个思路小小总结一下。
①原有文件存取日志的方式,运行得很好,如图4.7所示:
图4.7 原有文件存取日志的方式
②现在有了新的基于数据库的实现,新的实现有自己的接口,如图4.8所示:
图4.8 新的基于数据库的实现
③现在想要在第二版的实现里面,能够同时兼容第一版的功能,那么就应有一个类来实现第二版的接口,然后在这个类里面去调用已有的功能实现,这个类就是适配器,如下图4.9所示:
图4.9 加入适配器的实现结构示意图
上面是分步的思路,现在来看一下前面示例的整体结构,如图4.10所示:
图4.10 适配器实现的示例的结构示意图
如同上面的例子,原本新的日志操作接口不能和旧的文件实现一起工作,但是经过适配器适配后,新的日志操作接口就能和旧的文件实现日志存储一起工作了。
相关推荐
今天我们要探讨的是JAVA设计中的两个重要模式:抽象类与适配器模式。 首先,我们来理解一下“抽象”。抽象是面向对象编程的核心概念之一,它帮助我们处理对象的复杂性。在Java中,抽象通常通过抽象类来实现。抽象类...
在这个Java实现中,我们将深入探讨适配器模式的两大类型:类适配器模式和对象适配器模式,并通过具体的代码示例和UML类图来阐述其工作原理。 首先,我们来理解适配器模式的基本概念。适配器模式就像现实生活中的...
2. 适配器(Adapter)类:这是适配器模式的核心,它实现了目标接口,并持有对适配者对象的引用。适配器类负责将适配者的接口转换为目标接口。 3. 适配者(Adaptee)类:这是需要适配的原始接口或类,它的接口与目标...
适配器模式是一种在软件工程中广泛使用的结构型设计模式,它允许两个不兼容的接口之间进行通信。在Java中,适配器模式扮演着重要的角色,尤其在处理遗留代码或者第三方库集成时,能够有效地解决接口不匹配的问题。...
2. **类适配器模式** 在类适配器模式中,适配器类会继承目标接口和适配者类。这样做的好处是可以直接重用适配者类的一些方法,但缺点是当有多个适配者类需要适配时,可能会导致类的继承层次过于复杂。 3. **对象...
2. 对象适配器模式: 对象适配器模式中,适配器类并不直接继承目标接口,而是包含一个原始不兼容接口的对象。适配器通过实现目标接口并调用包含对象的相应方法来实现转换。这种方式更灵活,因为C++的组合可以随时...
Java动态代理模式与适配器模式是两种在软件设计中常用的设计模式,它们都有各自的优点和应用场景。在Java中,动态代理模式主要依赖于Java的反射API和InvocationHandler接口,而适配器模式则用于解决不同接口之间的...
适配器模式是一种设计模式,它允许不兼容的类或接口之间进行通信,通过创建一个适配器类作为中间桥梁,使得原本不匹配的接口能够协同工作。在Java中,适配器模式广泛应用于系统集成、旧代码复用以及第三方库的兼容性...
适配器模式可以通过创建一个Adapter类,实现新的DBConnection2接口,内部持有DBConnection实例,并在Adapter类中转换调用方法,使得客户端可以统一地使用DBConnection2接口。 5. **实现注意事项**: - 适配器的...
2. 对象适配器模式:通过组合原始类并实现目标接口来实现。这种方式更加灵活,因为一个类可以组合多个其他类,不受单继承限制。 在这个“adapter”压缩包中,我们可能会看到以下几个关键部分: 1. `Adapter` 类:...
2. 对象适配器模式:适配器类包含一个原始接口实现的对象,并通过方法委托来实现目标接口。这种方式更灵活,因为它支持多态,即使原始接口改变,也可以通过更换内部的对象来适应变化。 3. 接口适配器模式:适配器类...
2. 对象适配器模式:适配器类持有被适配者的实例,并通过方法调用来实现目标接口。这种方式更为灵活,因为适配器和被适配者之间是关联关系,即使被适配者是接口或抽象类,也可以进行适配。 3. 接口适配器模式:当...
适配器模式是一种常用的设计模式,它在软件工程中扮演着重要的角色,特别是在解决系统间的兼容性和接口不匹配问题时。适配器模式的核心思想是将一个类的接口转换成客户希望的另一个接口,使原本由于接口不兼容而无法...
适配器模式是一种软件设计模式,它在不同的接口之间起到了桥梁的作用,使得原本由于接口不兼容而无法协作的类能够协同工作。这种模式的核心思想是将一个类的接口转换成客户希望的另一个接口,从而使原有类能适应新的...
适配器模式是一种常用的设计模式,它在软件工程中扮演着重要的角色,允许不同接口的类之间进行通信。适配器模式的核心思想是将一个类的接口转换成客户期望的另一个接口,使得原本由于接口不兼容而无法一起工作的类...
### Java设计模式之适配器模式详解 #### 引言 在软件开发中,我们经常遇到需要使用已有的类库,但这些类库的接口与我们的需求不匹配的情况。这时,适配器模式(Adapter Pattern)便能派上用场。适配器模式是一种...