1 場(chǎng)景
系統(tǒng)中經(jīng)常會(huì)記錄數(shù)據(jù)的更改日志,記錄數(shù)據(jù)的變更前的內(nèi)容和變更后的內(nèi)容。而且有時(shí)候會(huì)記錄數(shù)據(jù)的多個(gè)字段的變更前和變更后的內(nèi)容(如狀態(tài)的變更前后、用戶(hù)的變更前后、金額的變更前后,而且有的內(nèi)容不發(fā)生變更的時(shí)候,不需要進(jìn)行記錄)。
如果現(xiàn)在有個(gè)日志記錄類(lèi),如下:
@Data
public class RecordChangeLog {
/**
* 操作
*/
private String operate;
/**
* 操作人
*/
private String operateUser;
/**
* 操作時(shí)間
*/
private Long operateTime;
/**
* “狀態(tài)”變更前
*/
private String statusBefore;
/**
* ”狀態(tài)“變更后
*/
private String statusAfter;
/**
* "金額"變更前
*/
private BigDecimal moneyBefore;
/**
* "金額"更能后
*/
private BigDecimal moneyAfter;
}
此種需求經(jīng)常的實(shí)現(xiàn)方式是:
RecordChangeLog recordChangeLog = new RecordChangeLog();
recordChangeLog.setOperate("xxx操作");
recordChangeLog.setOperateUser("張三");
recordChangeLog.setOperateTime(System.currentTimeMillis());
// 如果“狀態(tài)Status”變更了,則記錄
recordChangeLog.setStatusBefore("變更前狀態(tài)");
recordChangeLog.setStatusBefore("變更后狀態(tài)");
// 如果“金額Money”變更了,則記錄
recordChangeLog.setMoneyBefore(new BigDecimal(100));
recordChangeLog.setMoneyAfter(new BigDecimal(200));
此種方式,缺點(diǎn)如下:
- 寫(xiě)set方法設(shè)置參數(shù)的時(shí)候,容易漏掉,或者寫(xiě)錯(cuò)調(diào)用的set方法,導(dǎo)致日志記錄的錯(cuò)誤。
- 代碼冗余量太大,如果日志記錄的屬性較多時(shí),封裝成通用方法也較為復(fù)雜
- 代碼不明確,無(wú)法明確此次記錄到底需要更改記錄哪些屬性。
2 代碼實(shí)現(xiàn)
下面將使用更優(yōu)化的代碼實(shí)現(xiàn)日志變更記錄。
/**
* 日志包裝器
*/
public class RecordChangeLogWrapper {
/**
* 日志實(shí)體類(lèi)
*/
private RecordChangeLog recordChangeLog;
/**
* 構(gòu)造函數(shù)
* @param operate 操作類(lèi)型(可用枚舉類(lèi)替代)
* @param operateUser 操作人
*/
public RecordChangeLogWrapper(String operate, String operateUser) {
if (StringUtils.isEmpty(operate) || StringUtils.isEmpty(operateUser)) {
throw new IllegalArgumentException("operate or operateUser is null");
}
recordChangeLog = new RecordChangeLog();
recordChangeLog.setOperate(operate);
recordChangeLog.setOperateUser(operateUser);
recordChangeLog.setOperateTime(System.currentTimeMillis());
}
/**
* 獲取實(shí)例
* @return
*/
public RecordChangeLog getInstance(){
return this.recordChangeLog;
}
/**
* 變更“狀態(tài)”
* @param statusBefore “狀態(tài)”變更前
* @param statusAfter “狀態(tài)”變更后
* @return
*/
public RecordChangeLogWrapper changeStatus(String statusBefore, String statusAfter) {
this.recordChangeLog.setStatusBefore(statusBefore);
this.recordChangeLog.setStatusAfter(statusAfter);
return this;
}
/**
* 變更“金額”
* @param moneyBefore "金額"變更前
* @param moneyAfter "金額"變更后
* @return
*/
public RecordChangeLogWrapper changeMoney(BigDecimal moneyBefore, BigDecimal moneyAfter) {
this.recordChangeLog.setMoneyBefore(moneyBefore);
this.recordChangeLog.setMoneyAfter(moneyAfter);
return this;
}
}
使用方式如下:
// 更改狀態(tài)和金額
RecordChangeLogWrapper recordChangeLogWrapper1 = new RecordChangeLogWrapper("xx操作", "張三").changeStatus("待審核", "審核通過(guò)").changeMoney(new BigDecimal(100), new BigDecimal(200));
RecordChangeLog recordChangeLog1 = recordChangeLogWrapper1.getInstance();
// 更改狀態(tài)
RecordChangeLogWrapper recordChangeLogWrapper2 = new RecordChangeLogWrapper("xx操作", "張三").changeStatus("待審核", "審核通過(guò)");
RecordChangeLog recordChangeLog2 = recordChangeLogWrapper2.getInstance();
// 更改金額
RecordChangeLogWrapper recordChangeLogWrapper3 = new RecordChangeLogWrapper("xx操作", "張三").changeMoney(new BigDecimal(100), new BigDecimal(200));
RecordChangeLog recordChangeLog3 = recordChangeLogWrapper3.getInstance();