需求:制作一个日志管理系统,分为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());
} }

研磨设计模式学习笔记3--适配器模式Adapter的更多相关文章

  1. 研磨设计模式学习笔记4--单例模式Signleton

    需求:加载配置文件,由于配置文件全局唯一,所以不用过多对象,建一个就可以了. 优点:单例模式本质就是为了控制实例数目. 一.饿汉式 public class Singleton { private S ...

  2. 研磨设计模式学习笔记2--外观模式Facade

    需求:客户端需要按照需求,执行一个操作,操作包括一个系统中的3个模块(根据配置选择是否全部执行). 外观模式优点: 客户端无需知道系统内部实现,,只需要写好配置文件,控制那些模块执行,简单易用. 外观 ...

  3. 研磨设计模式学习笔记1--简单工厂(SimpleFactory)

    需求:实现一个简单工厂,客户端根据需求获取实现类. 简单工厂优点: 客户端不需要知道工厂内部实现,然组件外部实现面向接口编程. 客户端.实现类解耦. 一.接口及实现类 //接口 public inte ...

  4. 7 种 Javascript 常用设计模式学习笔记

    7 种 Javascript 常用设计模式学习笔记 由于 JS 或者前端的场景限制,并不是 23 种设计模式都常用. 有的是没有使用场景,有的模式使用场景非常少,所以只是列举 7 个常见的模式 本文的 ...

  5. 设计模式(五)适配器模式Adapter(结构型)

      设计模式(五)适配器模式Adapter(结构型) 1. 概述: 接口的改变,是一个需要程序员们必须(虽然很不情愿)接受和处理的普遍问题.程序提供者们修改他们的代码;系统库被修正;各种程序语言以及相 ...

  6. C#设计模式学习笔记-单例模式随笔

    最近学习 设计模式,从单例模式入手 啥是单例模式: 要实现一个单例类的话,首先,肯定是不能让用户自行生产的,那就是说明不能让用户new,所以,就必须把构造函数设置成为私有的 因为静态变量的生命周期跟整 ...

  7. 设计模式学习笔记--备忘录(Mamento)模式

    写在模式学习之前 什么是设计模式:在我们进行程序设计时,逐渐形成了一些典型问题和问题的解决方式,这就是软件模式:每个模式描写叙述了一个在我们程序设计中常常发生的问题,以及该问题的解决方式:当我们碰到模 ...

  8. C#设计模式学习笔记-单例模式(转)

    C#设计模式学习笔记-单例模式 http://www.cnblogs.com/xun126/archive/2011/03/09/1970807.html 最近在学设计模式,学到创建型模式的时候,碰到 ...

  9. Java设计模式学习笔记(二) 简单工厂模式

    前言 本篇是设计模式学习笔记的其中一篇文章,如对其他模式有兴趣,可从该地址查找设计模式学习笔记汇总地址 正文开始... 1. 简介 简单工厂模式不属于GoF23中设计模式之一,但在软件开发中应用也较为 ...

随机推荐

  1. parseXXX的用法

    转换字符串. parseXXX是Integer类.等基本数据类型包装类的方法,用于实现String和int型数据的转换.例如, Integer.getInteger(String s) 从字符串中获取 ...

  2. Luogu 3629 [APIO2010]巡逻

    先考虑$k = 1$的情况,很明显每一条边都要被走两遍,而连成一个环之后,环上的每一条边都只要走一遍即可,所以我们使这个环的长度尽可能大,那么一棵树中最长的路径就是树的直径. 设直径的长度为$L$,答 ...

  3. python3-函数的参数的四种简单用法:

    def print_two(*args):     arg1, arg2 = args     print "arg1: %r, arg2: %r" % (arg1,arg2)   ...

  4. git命令(二)

    2.查看.添加.提交.删除.找回,重置修改文件 3.查看文件diff git diff <file> # 比较当前文件和暂存区文件差异 git diff git diff <$id1 ...

  5. java Servlet学习笔记(一)

    访问机制 (https://pan.baidu.com/share/link?shareid=3055126243&uk=3355579678&fid=1073713310362078 ...

  6. C#中的线程池使用(二)

    线程池是后台线程.每个线程都使用默认的堆栈大小,以默认的优先级运行,并处于多线程单元中.每个进程只有一个线程池对象. 下面说一下线程池中的异常,在线程池中未处理的异常将终止进程.以下为此规则的三种例外 ...

  7. java 集合(转载)

    一.集合与数组 数组(可以存储基本数据类型)是用来存现对象的一种容器,但是数组的长度固定,不适合在对象数量未知的情况下使用. 集合(只能存储对象,对象类型可以不一样)的长度可变,可在多数情况下使用. ...

  8. ubuntu17.04安装flash

    因为用不了软件商店(别问我为什么) 所以手动安装 1 下载文件 在firefox下下载  *****.tar.gz 压缩包 ,并解压(一般目录在 /home 当前用户下的 下载目录下) adobe官网 ...

  9. 在Python中正确使用Unicode

    正确处理文本,特别是正确处理Unicode.是个老生常谈的问题,有时甚至会难倒经验丰富的开发者.并不是因为这个问题很难,而是因为对软件中的文本,开发者没有正确理解一些关键概念及其表示方法.在Stack ...

  10. 轻量级编辑器透彻指南--Notepad++

    Notepad++是Windows环境下的一款编辑器.比起VSCode等现代编辑器,Notepad++同样具备很多功能.Notepad++一个特点就是轻巧,方便在Windows环境中使用,且编辑功能强 ...