開竅了!如何為緩存工具類(CacheUtil中的static方法)定義interface(上)
兩個不同策略的緩存工具類
在我們系統的基建包里,有一個基于redis的get/set等基礎api封裝的 CacheUtil。
CacheUtil 主要有下面2個靜態方法:
import java.util.function.Supplier;
public class CacheUtil {
/**
* 獲取緩存。如果沒有,則設置
*/
public static <T> T getCache(String key, long seconds, Supplier<T> supplier) {
return getCache(key, seconds, false, supplier);
}
/**
* 獲取緩存。如果沒有,則設置
*/
public static <T> T getCache(String key, long seconds, boolean cacheNull, Supplier<T> supplier) {
Object obj = redisUtil.get(key); // 這里的RedisUtil類封裝了 redis 的get/set等基礎操作
if (null == obj) {
T value = supplier.get();
......
redisUtil.set(key, value, seconds);
return value;
} else {
......
return (T) obj;
}
}
}
隨著后續系統迭代過程中,我增加了一個基于本地緩存框架 hutool-cache 的 LFUCache、TimedCache 來實現的 LocalCacheUtil。
與 CacheUtil 一樣的是,LocalCacheUtil 中也主要有下面2個靜態方法:
import java.util.function.Supplier;
public class CacheUtil {
/**
* 獲取緩存。如果沒有,則設置
*/
public static <T> T getCache(String key, long seconds, Supplier<T> supplier) {
return getCache(key, seconds, false, supplier);
}
/**
* 獲取緩存。如果沒有,則設置
*/
public static <T> T getCache(String key, long seconds, boolean allowCacheNullOrEmpty, Supplier<T> supplier) {
return getCache(timedCache, key, seconds, allowCacheNullOrEmpty, supplier);
}
private static <T> T getCache(Cache<String, Object> myCache, String key, Long seconds, boolean allowCacheNullOrEmpty, Supplier<T> supplier) {
Object cachedValue = myCache.get(key, false);
if (cachedValue != null) {
return (T) cachedValue;
}
// 允許緩存null值的情況下,如果存在緩存,則直接返回
if (allowCacheNullOrEmpty && myCache.containsKey(key)) {
return (T) myCache.get(key, false);
}
......
T result = supplier.get();
if (seconds == null) {
myCache.put(key, result);
} else {
myCache.put(key, result, TimeUnit.SECONDS.toMillis(seconds));
}
return result;
}
}
如何為兩個緩存工具類抽取公共能力?
翻閱 git 提交記錄,我發現 CacheUtil 是2020-09 創建的,LocalCacheUtil 是 2022-12 創建的。
雖然兩年多過去了,但這其中有一個困擾著我的程序設計問題并沒有被遺忘。
這個程序設計問題是, CacheUtil 與 LocalCacheUtil 的職責是相同的,兩者都是用來緩存數據。那么,如果能夠為兩者抽象出來一個緩存數據的 interface,該多香啊!
可是, getCache 方法是 static 靜態方法。我們知道,靜態方法是無法實現接口的。
我總不能把 getCache 方法改為非靜態方法吧?
我不能。倒不是因為需要改所有的調用代碼,而是在程序設計原則中,工具類的設計理念通常是為了提供一組相關的實用方法,這些方法不依賴于類的實例狀態,而是專注于執行特定的功能。代碼實現中,我們通常將工具類的方法定義為 static 或者通過其他方式(如私有化構造函數)防止類在外部被實例化。
那么,我沒有辦法了!
我曾經在遙遠的2017年聽過一個架構師講過類似場景的解決方案,可惜的是,忘卻了,腦子里只留下“講解過”這三個字了。
直到最近,我才想到方案。(>>點擊下一篇查看)
當看到一些不好的代碼時,會發現我還算優秀;當看到優秀的代碼時,也才意識到持續學習的重要!--buguge
本文來自博客園,轉載請注明原文鏈接:http://www.rzrgm.cn/buguge/p/18850518
浙公網安備 33010602011771號