需求:制作一个日志管理系统,分为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. 10.model/view实例(4)

    任务:给表单的每一列添加列名. 思考: 1.只需要添加一个函数 headerData(). 横向方面添加列名 代码如下: QVariant MyModel::headerData(int sectio ...

  2. 《Maven实战》笔记-8-构建部署Web项目

      一.Web项目结构 1.显式指定Web项目打包方式为war:   2.默认目录 根据“约定大于配置”的规则,Web项目的类及资源文件默认位置为src/main/java和src/main/reso ...

  3. 通配符的匹配很全面, 但无法找到元素 'tx:annotation-driven'

    配置Spring时出现如题这个错误,下面是xml的内容 <?xml version="1.0" encoding="UTF-8"?> <bea ...

  4. java多线程系列:通过对战游戏学习CyclicBarrier

    CyclicBarrier是java.util.concurrent包下面的一个工具类,字面意思是可循环使用(Cyclic)的屏障(Barrier),通过它可以实现让一组线程到达一个屏障(也可以叫同步 ...

  5. linux 进程间通信机制(IPC机制)一消息队列

    消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法.每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构.我们可以通过发送消息来避免命名管道的同步和阻塞问题.但是消息 ...

  6. 认识data-xxx 的属性

    认识data-xxx 的属性 如, 在bootstrap之data-toggle="table", 不加这个属性,就不能实现框架自带的js效果. 1.它属于 HTML5 的 dat ...

  7. EIP权限工作流升级说明-2019/3/12

    流程配置界面,允许流程处理按钮名称自定义:适用于流程过程中显示不同字面意思.流程节点按钮配置界面 流程处理过程中

  8. 「BZOJ 2440」完全平方数「数论分块」

    题意 \(T\)组数据,每次询问第\(k\)个无平方因子的数(\(1\)不算平方因子),\(T\leq 50,k\leq 10^9\) 题解 \(k\)的范围很大,枚举肯定不行,也没什么奇妙性质,于是 ...

  9. 拖放(Drag和Drop)--html5

    拖放,就是抓取一个对象后拖放到另一个位置.很常用的一个功能,在还没有html5的时候,我们实现这个功能,通常会用大量的js代码,再利用mousemove,mouseup等鼠标事件来实现,总的来说比较麻 ...

  10. 【图灵学院15】极致优化-高性能网络编程之BIO与NIO区别

    一.Java IO概念 1.  一个http请求节点 数据传输 1)网络传输 TCP.UDP 2)通信模型 BIO.NIO.AIO 数据处理 3)应用协议 HTTP.RMI.WEBSERVICE.Re ...