给小白举个例子:
大家都用过macbook pro(15款)笔记本, tmd没有网线端口!没有VGA 视频输出接口 !
tmd 用网线要买转换器!开会用投影仪要买视频输出转接口!
这里的转换器和转接口就是我今天要讲的主角:适配器。
这里 我举个项目中的案例,做说明:
我现在要做个日志系统,前期功能比较单一,这里我叫它第一版,就是把日志写入文件,这个ok?
1:先整个日志类
public class LogModel { private String logId; private String operateUser; private String operateTime; private String logContent; get / set 省略...
public interface LogFileService { List<LogModel> readLogFile(); void writeLogFile(List<LogModel> list); }
public class LogFileServiceImpl implements LogFileService { @Override public List<LogModel> readLogFile() { System.out.println("正在读文件日志"); return null; } @Override public void writeLogFile(List<LogModel> list) { System.out.println("正在写入文件日志"); } }
LogModel logModel = new LogModel(); LogFileService service = new LogFileServiceImpl(); service.writeLogFile(null); service.readLogFile(); System.out.println("第一版 将日志写入文件!测试完成!");
看上去很容易,是吧,别急,我们接着来!
日志写入文件系统用了一段时间,老板需求增加了,我们要做系统升级,现在我们要把日志记录到DB 数据库中,
6:于是我就把接口定义好了,日志写入DB 接口如下:(这里不与数据库交互, 意思下示例)
public interface LogDBService { void createDBLog(LogModel logModel); void updateDBLog(LogModel logModel); void deleteDBLog(String logId); void selectDBLog(LogModel logModel); }
public class LogDBServiceImpl implements LogDBService { @Override public void createDBLog(LogModel logModel) { System.out.println("DB日志插入成功"); } @Override public void updateDBLog(LogModel logModel) { System.out.println("DB日志更新成功"); } @Override public void selectDBLog(LogModel logModel) { System.out.println("DB日志查询成功"); } }
很多同学心里一下子又答案了,当然了!当然都能支持了,但是实现方式不一定想的是相同的!
有的同学先到继承 ,对,设计个新接口,然后继承老的和新的接口功能,
但是,java继承只能继承一个不能同时继承,若果使用继承在继承实现,就不符合面向对象的原则了,!这里不多说。
7:这里就用到了适配器模式,就是我们找个适配器,就能用新接口兼容老的接口了!
这里我代码示例,把旧版接口功能适配成新版接口功能:我们先设计个适配器如下:
public class Adapter implements LogDBService { //被适配的对象 private LogFileService adaptee; //构造方法,传入要被适配的对象 public Adapter(LogFileService adaptee) { this.adaptee = adaptee; } @Override public void createDBLog(LogModel logModel) { adaptee.writeLogFile(null); } @Override public void updateDBLog(LogModel logModel) { //1;先读取 List<LogModel> list = adaptee.readLogFile(); for (int i = 0; i < list.size(); i++) { //2:修改内容 } //3:重新写入 adaptee.writeLogFile(list); } @Override public void selectDBLog(LogModel logModel) { adaptee.readLogFile(); } }
8:我们客户端调用也要稍微调整下:
LogModel logModel = new LogModel(); LogFileService fileService = new LogFileServiceImpl(); LogDBService dbService = new Adapter(fileService); dbService.createDBLog(null); dbService.selectDBLog(logModel); logFileClient(); System.out.println("文件适配成DB ,测试完成!");
我们使用的是第二版的接口,但实现的却是是第一版的功能,因为中间我们用到了一个适配器Adaper,
就像我们网线转换器一样,用的是USB接口,我们用它确实实现网络连接!
9: 到此我们新的客户端通过新的接口(第二版接口) ,能使用新功能,也能使用老功能了,如图:
10:老板在这时候,有提出了个需求,老的项目也要使用新版日志系统和新版日志功能,
这里有个问题了,我们老的项目,旧的客户端怎么搞?旧的只有旧接口,没有新版接口啊(读到这里,想到复制代码自己实现的同学,可以先不用学设计模式了)
这里给大家介绍个双向适配器!(上面演示的是个单向适配器),双向适配器的作用就是双向兼容!
上图示例说明:
11:双向适配器代码示例:
public class TwoDirectAdapter implements LogDBService,LogFileService{ private LogFileService logFileAdaptee; private LogDBService logDBAdaptee; public TwoDirectAdapter(LogFileService logFileAdaptee, LogDBService logDBAdaptee) { this.logFileAdaptee = logFileAdaptee; this.logDBAdaptee = logDBAdaptee; } @Override public void createDBLog(LogModel logModel) { logFileAdaptee.writeLogFile(null); } @Override public void updateDBLog(LogModel logModel) { //1;先读取 List<LogModel> list = logFileAdaptee.readLogFile(); for (int i = 0; i < list.size(); i++) { //2:修改内容 } //3:重新写入 logFileAdaptee.writeLogFile(null); } @Override public void selectDBLog(LogModel logModel) { logFileAdaptee.readLogFile(); } @Override public List<LogModel> readLogFile() { logDBAdaptee.selectDBLog(null); return null; } @Override public void writeLogFile(List<LogModel> list) { logDBAdaptee.createDBLog(null); } }
//双向兼容,双向适配器
System.out.println("===========双向适配器测试开始============"); //创建操作日志文件对象 LogFileService fileSer = new LogFileServiceImpl(); LogDBService dbSer = new LogDBServiceImpl(); //创建经过双向适配器后的操作日志的接口对象 LogFileService logFileSer = new TwoDirectAdapter(fileSer,dbSer); LogDBService dbFileSer = new TwoDirectAdapter(fileSer,dbSer); //调用第一版,实际是第二版实现 logFileSer.readLogFile(); logFileSer.writeLogFile(null); //调用第二版,实际是第一版实现 dbFileSer.createDBLog(null); dbFileSer.selectDBLog(null); System.out.println("===========双向适配器测试完成============");
13:测试结果如下:利用双向适配器,旧系统也能使用新版日志系统包括其所有功能了。
15:什么场景下使用适配器?