需求:制作一个日志管理系统,分为2个版本,第一版制作一个将日志存在本地文件的管理系统,第二版制作一个存储在数据库的管理系统,同时,第二版兼容第一版。
优点:可以复用现有功能,无需重新开发。
一、第一版日志系统存储本地
日志domain类
@Data @Builder public class LogModel implements Serializable{ private String logId; private String operUser; private String operTime; @Override public String toString() { return "LogModel{" + "logId='" + logId + '\'' + ", operUser='" + operUser + '\'' + ", operTime='" + operTime + '\'' + ", content='" + content + '\'' + '}'; } private String content; }
日志管理接口
public interface LogFileOperateApi { void writeLogFile(List<LogModel> list); List<LogModel> readLogFile(); }
日志管理实现类
public class LogFileOperateImpl implements LogFileOperateApi { private String logFilePathName = ""; LogFileOperateImpl(String logFilePathName){ File file = new File(logFilePathName); if(!file.exists()){ try { file.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } this.logFilePathName = logFilePathName; } @Override public void writeLogFile(List<LogModel> list) { try { ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(new File(logFilePathName))); objectOutputStream.writeObject(list); } catch (Exception e) { e.printStackTrace(); } } @Override public List<LogModel> readLogFile() { List<LogModel> list = null; ObjectInputStream objectInputStream = null; try { objectInputStream = new ObjectInputStream(new FileInputStream(new File(logFilePathName))); } catch (Exception e) { e.printStackTrace(); } try { list = (List<LogModel>) objectInputStream.readObject() ; } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } return list; } }
客户端
public class Client { public static void main(String[] args) { LogFileOperateApi logFileOperateImpl = new LogFileOperateImpl("d:/1.log"); List<LogModel> list = new LinkedList<>(); list.add(LogModel.builder().logId("1").operTime("2900-10-14").operUser("lby").content("hallo").build()); list.add(LogModel.builder().logId("2").operTime("2900-10-15").operUser("lby").content("hello").build()); logFileOperateImpl.writeLogFile(list); List<LogModel> logModels = logFileOperateImpl.readLogFile(); System.out.println(logModels); } }
到此,第一版日志系统已经完成。
二、第二版日志系统存储数据库
日志管理接口
public interface LogDbOperateApi { void createLog(List<LogModel> list); void removeLog(LogModel logModel); void updateLog(LogModel logModel); List<LogModel> getAllLogs(); }
日志管理实现类(简化了实现过程)
public class LogDbOperateImpl implements LogDbOperateApi{ @Override public void createLog(List<LogModel> list) { System.out.println("DB createLog"+list); } @Override public void removeLog(LogModel logModel) { System.out.println("DB removeLog"+logModel); } @Override public void updateLog(LogModel logModel) { System.out.println("DB updateLog"+logModel); } @Override public List<LogModel> getAllLogs() { System.out.println("DB getAllLogs"); return null; } }
客户端测试
public class Client { public static void main(String[] args) { LogDbOperateApi logDbOperateApi = new LogDbOperateImpl(); List <LogModel> list = new ArrayList<>(); list.add(LogModel.builder().content("test").build()); logDbOperateApi.createLog(list); logDbOperateApi.removeLog(LogModel.builder().content("test").build()); logDbOperateApi.updateLog(LogModel.builder().content("test").build()); logDbOperateApi.getAllLogs(); } }
三、第二版日志管理系统也开发好了,这个时候客户需要第二版的管理系统兼容第一版。
改造:无需重新开发支持第一版,引入adapter利用现有的LogFileOperateApi接口,转化为LogDbOperateApi接口。
public class Adapter implements LogDbOperateApi { LogFileOperateApi logFileOperateApi; Adapter(LogFileOperateApi logFileOperateApi){ this.logFileOperateApi = logFileOperateApi; }
@Override public void createLog(List<LogModel> list) { logFileOperateApi.writeLogFile(list); }
@Override public void removeLog(LogModel logModel) { List<LogModel> list = logFileOperateApi.readLogFile(); list.forEach(item->{ logModel.getLogId().equals(item.getLogId()); list.remove(item); }); logFileOperateApi.writeLogFile(list); }
@Override public void updateLog(LogModel logModel) { List<LogModel> list = logFileOperateApi.readLogFile(); list.forEach(item->{ logModel.getLogId().equals(item.getLogId()); list.remove(item); }); list.add(logModel); logFileOperateApi.writeLogFile(list); }
@Override public List<LogModel> getAllLogs() { return logFileOperateApi.readLogFile(); } }
客户端测试
public class Client { public static void main(String[] args) { LogFileOperateApi logFileOperateImpl = new LogFileOperateImpl("d:/1.log"); LogDbOperateApi logDbOperateApi = new Adapter(logFileOperateImpl); System.out.println(logDbOperateApi.getAllLogs()); logDbOperateApi.updateLog(LogModel.builder().logId("1").operTime("6666-10-14").operUser("lby").content("hallo").build()); System.out.println(logDbOperateApi.getAllLogs()); } }
四、双向兼容
已经完成了第二版日志管理系统兼容第一版,继续改造,利用双向适配器将系统改造成,两个版本相互兼容。
public class TwoDeriectApater implements LogDbOperateApi,LogFileOperateApi { private LogDbOperateApi logDbOperateApi; private LogFileOperateApi logFileOperateApi; public TwoDeriectApater(LogDbOperateApi logDbOperateApi,LogFileOperateApi logFileOperateApi){ this.logDbOperateApi = logDbOperateApi; this.logFileOperateApi = logFileOperateApi; } /** * * --------------以下为第二版兼容第一版部分---------- */ @Override public void createLog(List<LogModel> list) { logFileOperateApi.writeLogFile(list); } @Override public void removeLog(LogModel logModel) { List<LogModel> list = logFileOperateApi.readLogFile(); list.forEach(item->{ logModel.getLogId().equals(item.getLogId()); list.remove(item); }); logFileOperateApi.writeLogFile(list); } @Override public void updateLog(LogModel logModel) { List<LogModel> list = logFileOperateApi.readLogFile(); list.forEach(item->{ logModel.getLogId().equals(item.getLogId()); list.remove(item); }); list.add(logModel); logFileOperateApi.writeLogFile(list); } @Override public List<LogModel> getAllLogs() { return logFileOperateApi.readLogFile(); } /** * * --------------以下为第一版兼容第二版部分---------- */ @Override public void writeLogFile(List<LogModel> list) { logDbOperateApi.createLog(list); } @Override public List<LogModel> readLogFile() { return logDbOperateApi.getAllLogs(); } }
客户端测试
public class Client { public static void main(String[] args) { LogFileOperateApi logFileOperateImpl = new LogFileOperateImpl("d:/1.log"); LogDbOperateApi logDbOperateImpl = new LogDbOperateImpl(); LogFileOperateApi fileApi = new TwoDeriectApater(logDbOperateImpl,logFileOperateImpl); LogDbOperateApi dbApi = new TwoDeriectApater(logDbOperateImpl,logFileOperateImpl); List<LogModel> list = new LinkedList<>(); list.add(LogModel.builder().logId("1").operTime("8888-10-14").operUser("lby").content("hallo").build()); list.add(LogModel.builder().logId("2").operTime("2222-10-15").operUser("lby").content("hello").build()); dbApi.createLog(list); System.out.println(dbApi.getAllLogs()); System.out.println(fileApi.readLogFile()); } }