1、设计模式之-适配器适配器模式先考虑这种设计模式适用场景:假如我们有一个运行良好的接口以及其实现,(Version 1.0,比如说是按照用户要求开 发的日志系统, 这个日志系统是基于文件 记录的FileLogger),但是由于系统升级或者用户需求变化等,我 们又设计了一个新的接口以及实现(Version 2.0,比如说是按照用户的要求,让日志系统是基于数据库记录 的DBLogger ),并且这个新设计的接口也能良好运行.假如到此为止,我们还没看出 设计模式的用武之地。然而,我们知道,用户的需求创意是无穷无尽的, 现在用户说了,我们想同时用这两种日志系 统.就是说,现如今的业务是运行在 Versi
2、on 2.0 的接口上,但是我要用 Version 1.0的实现.好,需求出来了,那么怎么实现呢?两个接口的方法都不一致(兼容)?说起来也简单,大约有这么 2套方案:1,我们按照DBLogger的接口,在重新开发一套,适用于文件系统的日志。2,直接修改Version 1.0 的代码。先说第一种方案,这么做确 实可以,而且很直 观。但是在我们已完成相应功能的前提下,再重新写一套代 码其实是没有必要的,并且代码复用性也不高。从这个角度考虑,如果有更好的 办法,我 们可以将这个方案pass掉。再说第二种方案,第二种方案也可以解决问题,但是它暴露的问题更加明显。如果直接修改第一版本的代码,那么很可能造
3、成其他依赖这些代 码的代码不能运行,也就是存在依赖 关系的约束。 这个方案还不如第一个方案,所以我们毫不犹豫的把它pass !两种方案都被否定了,下面就是 适配器模式 上场了。适配器模式作用:将一个接口转化为客户端希望的另一个接口,使得原本由于接口不相容的两个类,可以相互配合的一起工作。主要就是起一个转换器的作用,目的就是复用原来的功能,说白了就是让两个接口匹配起来。想想看,适配器的作用在生活中很常见,比如管道转接头,三相插座插口 转换器等。这就是 适配器模式 出现的背景.下面我们看一下代码的实现:首先看一下日志模型类(JavaBean):package mode.adaptor;/* 这是日
4、志对象的模型 简化点写,只有操作人和操作* * author root* */public class LogModel private String uuid;private String operator;/ 操作人private String operate;/ 操作private String timestamp;/ 操作时间public String getUuid() return uuid;public void setUuid(String uuid) this.uuid = uuid;public String getOperator() return operator;pu
5、blic void setOperator(String operator) this.operator = operator;public String getOperate() return operate;public void setOperate(String operate) this.operate = operate;public String getTimestamp() return timestamp;public void setTimestamp(String timestamp) this.timestamp = timestamp;public String to
6、String() return “用户 “ + this.getOperator() + “ 在 “ + this.getTimestamp()+ “ 做了 “ + this.getOperate() + “ 操作“;然后在看一下 Version 1.0的日志系统接口,面向文件的:package mode.adaptor;import java.util.List;/* 文件日志系统的操作接口* author root*/public interface FileLogger public List readLog();public void writeLog(LogModel model);
7、以及具体实现:package mode.adaptor;import java.util.List;/* 文件日志操作的简单实现* author root*/public class FileLoggerImpl implements FileLoggerOverridepublic List readLog() System.out.println(“读 取日志文件内容.“);return null;Overridepublic void writeLog(LogModel model) System.out.println(“写入日志文件: “+model);假设这就是我们使用的Versi
8、on1.0的代码,但是由于系统升级或者用户需求变化,倒是接口改变。如再下面就是 Version 2.0 的日志系统接口,是面向数据库的:package mode.adaptor;import java.util.List;/* 数据库文件系统的操作接口* author root*/public interface DBLogger public void addLog(LogModel model);public void updateLog(LogModel model);public void deleteLog(LogModel model);public List queryLog()
9、;以及具体实现:package mode.adaptor;import java.util.List;public class DBLoggerImpl implements DBLogger Overridepublic void addLog(LogModel model) System.out.println(“写入日志数据 库:“ + model);Overridepublic void updateLog(LogModel model) System.out.println(“更新日志数据 库:“ + model);Overridepublic void deleteLog(LogM
10、odel model) System.out.println(“删 除数据库日志:“ + model);Overridepublic List queryLog() System.out.println(“查询 数据库日志.“);return null;最后假设是业务使用这两种日志的测试方法:public class Client private FileLogger fileLogger = null;private LogModel model = null;private DBLogger dbLogger = null;Beforepublic void init() fileLogg
11、er = new FileLoggerImpl();dbLogger = new DBLoggerImpl();model = new LogModel();model.setUuid(“uuid“);model.setOperate(“update“);model.setOperator(“zhangsan“);model.setTimestamp(“2013-01-06 22:44:45“);/* 这是使用 Version 1.0 的业务代码*/Testpublic void useLog_v1() fileLogger.readLog();fileLogger.writeLog(mode
12、l);/*这是使用Version 2.0 的业务代码 */Testpublic void userLog_v2() dbLogger.addLog(model);dbLogger.updateLog(model);dbLogger.deleteLog(model);dbLogger.queryLog();目前为止,如果客户没有提出更加 变态的需求,那么代 码是可以良好运行的。但是假如说,用户又提出了一个新的需求,说我们想混合使用两种日志系 统.就得在Version2.0 接口的基础上,有一个Version1.0的实现.那么,怎么 办呢, 这就是适配器模式的用武之地:做接口转换!package
13、mode.adaptor;import java.util.List;/* 这个就是传说中的转换器类.起一个转换接口的作用* author root*/public class Adaptor implements DBLoggerprivate FileLogger filelogger = null;public Adaptor(FileLogger filelogger)this.filelogger = filelogger;Overridepublic void addLog(LogModel model) filelogger.writeLog(model);Overridepub
14、lic void updateLog(LogModel model) List list = filelogger.readLog();if(list = null)filelogger.writeLog(model);/文件日志更新:先读出来,然后在对象更新后重新写入,这里只是模拟elsefor(int i = 0; i 删除操作完成“);Overridepublic List queryLog() return filelogger.readLog();我们可以看出,适配器类必须实现 新版本(Version2.0)的接口,由于需要Version1.0的实现,所以在构造方法中需要一个Vers
15、ion1.0 的实现。然后想办法进行接口的 转换。有了适配器类,我们就可以在客 户端混合使用两种日志系统了:package mode.adaptor;import org.junit.Before;import org.junit.Test;public class Client private FileLogger fileLogger = null;private LogModel model = null;private DBLogger dbLogger = null;Beforepublic void init() fileLogger = new FileLoggerImpl();
16、dbLogger = new DBLoggerImpl();model = new LogModel();model.setUuid(“uuid“);model.setOperate(“update“);model.setOperator(“zhangsan“);model.setTimestamp(“2013-01-06 22:44:45“);/* 假设这是使用两种混合版本代码的业务*/Testpublic void useLogger_V12()System.out.println(“怎么 实现?“);System.out.println(“使用适配器模式 !“);DBLogger logger = new Adaptor(fileLogger);logger.addLog(model);logger.updateLog(model);logger.deleteLog(model);logger.queryLog();这,就是传说中的适配器模式!