=====开发第一阶段
客户第一阶段需求:
* 用户要求记录数据库操作日志,存储形式为文件;
* 记录信息有:日志流水号、执行人员、执行操作内容(更新/删除/插入等...)、执行时间;
开发分析:
* 定义日志模型,对日志对象进行序列化存文件。
* 实现日志存储方式
* 进行接口测试
UML设计图:
源码:
Client.java
package com.pattern.adapterlogmanger1;
import java.util.List;
import java.util.ArrayList;
/**
* 客户端
* @author yuanwm
*
*/
public class Client {
public static void main(String[] args) {
//定义测试数据
LogManage log = new LogManage();
log.setLogSerialNo("001");
log.setLogOperaUser("yuanwm");
log.setLogOperaType("update");
log.setLogOperaTime("2018-12-24 09:00:00");
log.setLogOperaContent("更新一个表");
List<LogManage> list = new ArrayList<LogManage>();
list.add(log);
//实例化日志操作对象
LogOpera logApi = new LogOpera("./log.txt");
//写日志
logApi.WriteLogFile(list);
//读取日志文件内容
List<LogManage> readList = logApi.readLogFile();
System.out.println("log="+readList);
}
}
LogManage.java
package com.pattern.adapterlogmanger1;
import java.io.Serializable;
/**
* 日志管理对象
* @author yuanwm
*/
public class LogManage implements Serializable {
/**
*实现 Serializable这个接口才能进行序列化。
*/
//一个设为固定的 1L,另一个是随机生成一个不重复的 long 类型数据(实际上是使用 JDK 工具生成)。
//一般如果没有特殊需求,用默认的 1L 就可以,这样可以确保反序列化成功。因为不同的序列化id之间不能进行序列化和反序列化。
private static final long serialVersionUID = 1L;
private String logSerialNo; //日志流水号
private String logOperaUser; //执行人员
private String logOperaType; //执行操作类型(更新/删除/插入等...)
private String logOperaContent; //执行操作内容
private String logOperaTime; //执行时间
public String getLogSerialNo() {
return logSerialNo;
}
public void setLogSerialNo(String logSerialNo) {
this.logSerialNo = logSerialNo;
}
public String getLogOperaUser() {
return logOperaUser;
}
public void setLogOperaUser(String logOperaUser) {
this.logOperaUser = logOperaUser;
}
public String getLogOperaType() {
return logOperaType;
}
public void setLogOperaType(String logOperaType) {
this.logOperaType = logOperaType;
}
public String getLogOperaContent() {
return logOperaContent;
}
public void setLogOperaContent(String logOperaContent) {
this.logOperaContent = logOperaContent;
}
public String getLogOperaTime() {
return logOperaTime;
}
public void setLogOperaTime(String logOperaTime) {
this.logOperaTime = logOperaTime;
}
public String toString(){
return "logSerialNo="+logSerialNo+",logOperaUser="+logOperaUser+",logOperaType="+logOperaType+","
+ "logOperaContent="+logOperaContent+ "," + "logOperaTime=" + logOperaTime;
}
}
LogOpera.java
package com.pattern.adapterlogmanger1;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.List;
/**
* 实现日志操作
* @author yuanwm
*
*/
public class LogOpera implements LogOperaApi {
private String logFilePathName = null;
public LogOpera(String inlogFilePathName ) {
// TODO Auto-generated constructor stub
if(inlogFilePathName !=null && inlogFilePathName.trim().length() > 0) {
this.logFilePathName = inlogFilePathName;
}
}
@Override
public List<LogManage> readLogFile() {
// TODO Auto-generated method stub
List<LogManage> listManage = null;
ObjectInputStream ioInputStream = null;
try {
File fpFile = new File(logFilePathName);
if(fpFile.exists()){
ioInputStream = new ObjectInputStream(
new BufferedInputStream( new FileInputStream(fpFile)
));
listManage = (List <LogManage>)ioInputStream.readObject();
}
}catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}finally {
try {
if(ioInputStream != null) {
ioInputStream.close();
}
}catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
return listManage;
}
@Override
public void WriteLogFile(List<LogManage> list) {
// TODO Auto-generated method stub
File fpFile = new File(logFilePathName);
ObjectOutputStream ioOutputStream = null;
try {
ioOutputStream = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(fpFile)));
ioOutputStream.writeObject(list);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}finally {
try {
if (ioOutputStream != null) {
ioOutputStream.close();
}
}catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
}
LogOperaApi.java
package com.pattern.adapterlogmanger1;
import java.util.List;
/**
* 日志操作的接口定义
* @author yuanwm
*
*/
public interface LogOperaApi {
/**
* 读取日志文件,从文件里获取日志存储的对象
* @return 存储日志的对象
*/
public List<LogManage> readLogFile();
/**
* 写日志文件,将日志对象写到文件中
* @param list 要写到日志文件的对象
*/
public void WriteLogFile(List<LogManage> list);
}
=====开发第二阶段
客户第二阶段需求:
* 客户要求增加日志存入数据库的功能,与原功能并用
开发分析:
* 定义数据库存储的接口
* 原客户端可以不变,新客户端就需要选择使用两个功能。
* 定义一个适配器,同时支持文件与数据库的操作。使用对象适配器。
UML:
增改源码:
Client.java
package com.pattern.adapterlogmanger2;
import java.util.List;
import java.util.ArrayList;
/**
* 客户端
*
* @author yuanwm
*
*/
public class Client {
public static void main(String[] args) {
// 定义测试数据
LogManage log = new LogManage();
log.setLogSerialNo("001");
log.setLogOperaUser("yuanwm");
log.setLogOperaType("update");
log.setLogOperaTime("2018-12-24 09:00:00");
log.setLogOperaContent("更新一个表");
List<LogManage> list = new ArrayList<LogManage>();
list.add(log);
// 实例化文件日志操作对象
LogOpera logApi = new LogOpera("./log.txt");
// 进行添加进最最新的适配
LogAdapter Adapter = new LogAdapter(logApi);
/**
* 原文件操作方式
*/
// 写日志
Adapter.WriteLogFile(list);
// 读取日志文件内容
List<LogManage> readList = Adapter.readLogFile();
System.out.println("log=" + readList);
/**
* 目前数据库的操作方式
*/
// 插入
Adapter.insertDbOpera(list);
// 更新
Adapter.updateDbOpera(list);
// 删除
Adapter.removeDbOpera(list);
// 查询
Adapter.queryDblog();
}
}
LogAdapter.java
package com.pattern.adapterlogmanger2;
import java.util.List;
/**
* 这是适配器的实现;
* 对于数据库操作jdb等过程暂不实现,这里主要注重模式的应用解决问题。
* @author yuanwm
*
*/
public class LogAdapter implements LogDbOperaApi {
private LogOpera logFileAdaptee;
public LogAdapter(LogOpera logFileAdaptee) {
this.logFileAdaptee = logFileAdaptee;
}
public List<LogManage> readLogFile() {
return logFileAdaptee.readLogFile();
}
public void WriteLogFile(List<LogManage> list) {
logFileAdaptee.WriteLogFile(list);
}
@Override
public void insertDbOpera(List<LogManage> loglist) {
// TODO Auto-generated method stub
System.out.println("以下日志已经插入数据库");
System.out.println("log:" + loglist);
}
@Override
public void updateDbOpera(List<LogManage> loglist) {
// TODO Auto-generated method stub
System.out.println("以下日志已经更新数据库");
System.out.println("log:" + loglist);
}
@Override
public void removeDbOpera(List<LogManage> loglist) {
// TODO Auto-generated method stub
System.out.println("以下日志已经从数据库删除");
System.out.println("log:" + loglist);
}
@Override
public List<LogManage> queryDblog() {
// TODO Auto-generated method stub
System.out.println("[测试]已经完成数据库数据查询");
return null;
}
}
LogDbOperaApi.java
package com.pattern.adapterlogmanger2;
import java.util.List;
/**
* 日志数据库操作API 新增,更新,删除,查询操作
*
* @author yuanwm
*
*/
public interface LogDbOperaApi {
/**
* 新增
*/
public void insertDbOpera(List<LogManage> loglist);
/**
* 更新
*/
public void updateDbOpera(List<LogManage> loglist);
/**
* 删除
*/
public void removeDbOpera(List<LogManage> loglist);
/**
* 查询所有日志
*/
public List<LogManage> queryDblog();
}
=====开发第三阶段
客户第三阶段需求:
* 客户要求第一版与第二版共存,但是主要还是使用第一版。意思是用第一版的接口,第一版的界面,
但是,实际操作的是第二版的DB。第二版也能操作第一版的方式。
* 在本实例中即:文件方式实际操作DB,DB方式实际操作文件。原第一版接口直接操作的DB。
开发分析:
* 定义数据库操作与接口
* 通过实现数据库、文件两个接口,达到一个双向适配器,即:文件-》数据库,数据库-》文件。
UML:
增改源码:
Client.java
package com.pattern.adapterlogmanger3;
import java.util.List;
import java.util.ArrayList;
/**
* 客户端
*
* @author yuanwm
*
*/
public class Client {
public static void main(String[] args) {
// 定义测试数据
LogManage log = new LogManage();
log.setLogSerialNo("001");
log.setLogOperaUser("yuanwm");
log.setLogOperaType("update");
log.setLogOperaTime("2018-12-24 09:00:00");
log.setLogOperaContent("更新一个表");
List<LogManage> list = new ArrayList<LogManage>();
list.add(log);
// 实例化文件日志操作对象
LogOperaApi logApi = new LogOpera("./log.txt");
// 实例化数据库操作对象
LogDbOperaApi dbApi = new LogDbOpera();
// 进行添加进最最新的适配
LogBothwayAdapter Adapter = new LogBothwayAdapter(logApi, dbApi);
/**
* 数据库是配到文件。
*/
// 写日志
Adapter.WriteLogFile(list);
// 读取日志文件内容,这里没有实现数据库过程,因此暂时不输出
Adapter.readLogFile();
/**
* 文件适配到数据库
*/
// 插入
Adapter.insertDbOpera(list);
System.out.println("插入后:log=" + Adapter.queryDblog());
// 更新
Adapter.updateDbOpera(list);
System.out.println("更新后:log=" + Adapter.queryDblog());
// 删除
Adapter.removeDbOpera(list);
System.out.println("删除后:log=" + Adapter.queryDblog());
}
}
LogDbOpera.java
package com.pattern.adapterlogmanger3;
/**
* 对logdb操作的简单实现
* 具体操作数据库的方式暂不实现,注重模式的应用解决问题
*/
import java.util.List;
public class LogDbOpera implements LogDbOperaApi {
@Override
public void insertDbOpera(List<LogManage> loglist) {
// TODO Auto-generated method stub
System.out.println("以下日志已经插入数据库");
System.out.println("log:" + loglist);
}
@Override
public void updateDbOpera(List<LogManage> loglist) {
// TODO Auto-generated method stub
System.out.println("以下日志已经更新数据库");
System.out.println("log:" + loglist);
}
@Override
public void removeDbOpera(List<LogManage> loglist) {
// TODO Auto-generated method stub
System.out.println("以下日志已经从数据库删除");
System.out.println("log:" + loglist);
}
@Override
public List<LogManage> queryDblog() {
// TODO Auto-generated method stub
System.out.println("[测试]已经完成数据库数据查询");
return null;
}
}
BothwayAdapter.java
package com.pattern.adapterlogmanger3;
import java.util.List;
/**
* 这是双向适配器的实现; 对于数据库操作jdb等过程暂不实现,这里主要注重模式的应用解决问题。 将Db操作实现为文件的方式,将file操作实现为db的方式;
* 调用db的方法实际是文件操作,调用文件的方法实际是db的操作 暂时选择与原实现方法名一致,如果不一致也不影响。
*
* @author yuanwm
*
*/
public class LogBothwayAdapter implements LogDbOperaApi, LogOperaApi {
private LogOperaApi logFileAdaptee;
private LogDbOperaApi logDbAdaptee;
public LogBothwayAdapter(LogOperaApi logFileAdaptee, LogDbOperaApi logDbAdaptee) {
this.logFileAdaptee = logFileAdaptee;
this.logDbAdaptee = logDbAdaptee;
}
/**
* db实现到文件的方法中
*/
public List<LogManage> readLogFile() {
return logDbAdaptee.queryDblog();
}
public void WriteLogFile(List<LogManage> list) {
logDbAdaptee.insertDbOpera(list);
}
/**
* file实现到Db的方法中
*/
@Override
public void insertDbOpera(List<LogManage> loglist) {
// TODO Auto-generated method stub
logFileAdaptee.WriteLogFile(loglist);
}
@Override
public void updateDbOpera(List<LogManage> loglist) {
// TODO Auto-generated method stub
List<LogManage> list = logFileAdaptee.readLogFile();
for (int i = 0; i < loglist.size(); i++) {
for (int j = 0; j < list.size(); j++) {
if (list.get(j).getLogSerialNo().equals(loglist.get(i).getLogSerialNo())) {
list.set(j, loglist.get(i));
break;
}
}
}
}
@Override
public void removeDbOpera(List<LogManage> loglist) {
// TODO Auto-generated method stub
List<LogManage> list = logFileAdaptee.readLogFile();
for (LogManage tmplog : loglist) {
for (int j = 0; j < list.size(); j++) {
if (list.get(j).getLogSerialNo().equals(tmplog.getLogSerialNo())) {
list.remove(j);
logFileAdaptee.WriteLogFile(list);
break;
}
}
}
}
@Override
public List<LogManage> queryDblog() {
// TODO Auto-generated method stub
return logFileAdaptee.readLogFile();
}
}
=====开发第四阶段(类适配器,与第二阶段需求一致)
UML设计:
增改源码,其他同第二阶段源码:
Client.java
package com.pattern.adapterlogmanger4;
import java.util.List;
import java.util.ArrayList;
/**
* 客户端
*
* @author yuanwm
*
*/
public class Client {
public static void main(String[] args) {
// 定义测试数据
LogManage log = new LogManage();
log.setLogSerialNo("001");
log.setLogOperaUser("yuanwm");
log.setLogOperaType("update");
log.setLogOperaTime("2018-12-24 09:00:00");
log.setLogOperaContent("更新一个表");
List<LogManage> list = new ArrayList<LogManage>();
list.add(log);
// 进行添加进最最新的适配
LogClassAdapter Adapter = new LogClassAdapter("./log.txt");
/**
* 原文件操作方式
*/
// 写日志
Adapter.WriteLogFile(list);
// 读取日志文件内容
List<LogManage> readList = Adapter.readLogFile();
System.out.println("log=" + readList);
/**
* 目前数据库的操作方式
*/
// 插入
Adapter.insertDbOpera(list);
// 更新
Adapter.updateDbOpera(list);
// 删除
Adapter.removeDbOpera(list);
// 查询
Adapter.queryDblog();
}
}
LogClassAdapter.java
package com.pattern.adapterlogmanger4;
import java.util.List;
/**
* 这是类适配器的实现;
* 对于数据库操作jdb等过程暂不实现,这里主要注重模式的应用解决问题。
* 由于是继承,且参数模板一致,因此可以直接调用。
* @author yuanwm
*
*/
public class LogClassAdapter extends LogOpera implements LogDbOperaApi {
public LogClassAdapter(String logPathName) {
super(logPathName);
}
@Override
public void insertDbOpera(List<LogManage> loglist) {
// TODO Auto-generated method stub
System.out.println("以下日志已经插入数据库");
System.out.println("log:" + loglist);
}
@Override
public void updateDbOpera(List<LogManage> loglist) {
// TODO Auto-generated method stub
System.out.println("以下日志已经更新数据库");
System.out.println("log:" + loglist);
}
@Override
public void removeDbOpera(List<LogManage> loglist) {
// TODO Auto-generated method stub
System.out.println("以下日志已经从数据库删除");
System.out.println("log:" + loglist);
}
@Override
public List<LogManage> queryDblog() {
// TODO Auto-generated method stub
System.out.println("[测试]已经完成数据库数据查询");
return null;
}
}
参考书籍:《Java设计模式(第2版)》、《设计模式可复用面向对象软件的基础》《设计模式可复用面向对象软件的基础》,参考其中源码,用于学习记录。