开窍了!如何为缓存工具类(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
本文来自博客园,转载请注明原文链接:https://www.cnblogs.com/buguge/p/18850518