适配器的插头
我们来看一下适配器的一个简单的代码案例
package cn.javass.dp.adapter.example1; /** * 已经存在的接口,这个接口需要被适配 */ public class Adaptee { /** * 示意方法,原本已经存在,已经实现的方法 */ public void specificRequest() { //具体的功能处理 } }
package cn.javass.dp.adapter.example1; /** * 适配器 */ public class Adapter implements Target { /** * 持有需要被适配的接口对象 */ private Adaptee adaptee; /** * 构造方法,传入需要被适配的对象 * @param adaptee 需要被适配的对象 */ public Adapter(Adaptee adaptee) { this.adaptee = adaptee; } public void request() { //可能转调已经实现了的方法,进行适配 adaptee.specificRequest(); } }
package cn.javass.dp.adapter.example1; /** * 定义客户端使用的接口,与特定领域相关 */ public interface Target { /** * 示意方法,客户端请求处理的方法 */ public void request(); }
package cn.javass.dp.adapter.example1; /** * 使用适配器的客户端 */ public class Client { public static void main(String[] args) { //创建需被适配的对象 Adaptee adaptee = new Adaptee(); //创建客户端需要调用的接口对象 Target target = new Adapter(adaptee); //请求处理 target.request(); } }
本质上就是对已经存在的功能进行封装,满足客户端心得需求
我们现在使用一个下面的功能。将日志文件保存到文件中
package cn.javass.dp.adapter.example2; import java.io.*; /** * 日志数据对象 */ public class LogModel implements Serializable{ /** * 日志编号 */ private String logId; /** * 操作人员 */ private String operateUser; /** * 操作时间,以yyyy-MM-dd HH:mm:ss的格式记录 */ private String operateTime; /** * 日志内容 */ private String logContent; public String getLogId() { return logId; } public void setLogId(String logId) { this.logId = logId; } public String getOperateUser() { return operateUser; } public void setOperateUser(String operateUser) { this.operateUser = operateUser; } public String getOperateTime() { return operateTime; } public void setOperateTime(String operateTime) { this.operateTime = operateTime; } public String getLogContent() { return logContent; } public void setLogContent(String logContent) { this.logContent = logContent; } public String toString(){ return "logId="+logId+",operateUser="+operateUser+",operateTime="+operateTime+",logContent="+logContent; } }
package cn.javass.dp.adapter.example2; import java.util.List; /** * 日志文件操作接口 */ public interface LogFileOperateApi { /** * 读取日志文件,从文件里面获取存储的日志列表对象 * @return 存储的日志列表对象 */ public List<LogModel> readLogFile(); /** * 写日志文件,把日志列表写出到日志文件中去 * @param list 要写到日志文件的日志列表 */ public void writeLogFile(List<LogModel> list); }
package cn.javass.dp.adapter.example2; import java.io.*; import java.util.*; /** * 实现对日志文件的操作 */ public class LogFileOperate implements LogFileOperateApi{ /** * 日志文件的路径和文件名称,默认是当前classpath下的AdapterLog.log */ private String logFilePathName = "AdapterLog.log"; /** * 构造方法,传入文件的路径和名称 * @param logFilePathName 文件的路径和名称 */ public LogFileOperate(String logFilePathName) { //先判断是否传入了文件的路径和名称,如果是, //就重新设置操作的日志文件的路径和名称 if(logFilePathName!=null && logFilePathName.trim().length()>0){ this.logFilePathName = logFilePathName; } } public List<LogModel> readLogFile() { List<LogModel> list = null; ObjectInputStream oin = null; try { File f = new File(logFilePathName); if(f.exists()){ oin = new ObjectInputStream( new BufferedInputStream(new FileInputStream(f)) ); list = (List<LogModel>)oin.readObject(); } } catch (Exception e) { e.printStackTrace(); }finally{ try { if(oin!=null){ oin.close(); } } catch (IOException e) { e.printStackTrace(); } } return list; } public void writeLogFile(List<LogModel> list){ File f = new File(logFilePathName); ObjectOutputStream oout = null; try { oout = new ObjectOutputStream( new BufferedOutputStream(new FileOutputStream(f)) ); oout.writeObject(list); } catch (IOException e) { e.printStackTrace(); }finally{ try { oout.close(); } catch (IOException e) { e.printStackTrace(); } } } }
客户端的使用
package cn.javass.dp.adapter.example2; import java.util.*; public class Client { public static void main(String[] args) { //准备日志内容,也就是测试的数据 LogModel lm1 = new LogModel(); lm1.setLogId("001"); lm1.setOperateUser("admin"); lm1.setOperateTime("2010-03-02 10:08:18"); lm1.setLogContent("这是一个测试"); List<LogModel> list = new ArrayList<LogModel>(); list.add(lm1); //创建操作日志文件的对象 LogFileOperateApi api = new LogFileOperate(""); //保存日志文件 api.writeLogFile(list); //读取日志文件的内容 List<LogModel> readLog = api.readLogFile(); System.out.println("readLog="+readLog); } }
现在在后面的开发中,我们需要使用数据库的形式来保存日志,最新的保存的日志使用最新的数据库的增加
删除 更新等四个接口,所以现在存在了两个版本的日志系统,第一个版本是日志文件系统,第二个版本是数据库系统,我们需要实现操作数据库的接口能够实现操作日志
我们使用适配器的模式来解决下面的代码
package cn.javass.dp.adapter.example3; import java.util.*; /** * 定义操作日志的应用接口,为了示例的简单, * 只是简单的定义了增删改查的方法 */ public interface LogDbOperateApi { /** * 新增日志 * @param lm 需要新增的日志对象 */ public void createLog(LogModel lm); /** * 修改日志 * @param lm 需要修改的日志对象 */ public void updateLog(LogModel lm); /** * 删除日志 * @param lm 需要删除的日志对象 */ public void removeLog(LogModel lm); /** * 获取所有的日志 * @return 所有的日志对象 */ public List<LogModel> getAllLog(); }
package cn.javass.dp.adapter.example4; import java.util.List; /** * DB存储日志的实现,为了简单,这里就不去真的实现和数据库交互了,示意一下 */ public class LogDbOperate implements LogDbOperateApi{ public void createLog(LogModel lm) { System.out.println("now in LogDbOperate createLog,lm="+lm); } public List<LogModel> getAllLog() { System.out.println("now in LogDbOperate getAllLog"); return null; } public void removeLog(LogModel lm) { System.out.println("now in LogDbOperate removeLog,lm="+lm); } public void updateLog(LogModel lm) { System.out.println("now in LogDbOperate updateLog,lm="+lm); } }
package cn.javass.dp.adapter.example3; import java.util.List; /** * 适配器对象,把记录日志到文件的功能适配成第二版需要的增删改查的功能 */ 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); } }
客户端的调用
package cn.javass.dp.adapter.example3; import java.util.*; public class Client { public static void main(String[] args) { //准备日志内容,也就是测试的数据 LogModel lm1 = new LogModel(); lm1.setLogId("001"); lm1.setOperateUser("admin"); lm1.setOperateTime("2010-03-02 10: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); } }
这样就是实现采用数据库的方式来适配第一版的日志系统
适配器的主要功能:
是复用已经存在的功能,被适配的对象adaptee和需要适配成新的对象Target接口,二者是毫无关系的