一 接口简单使用
在 lambda 表达式一节,接触了一个注解
@FunctionalInterface
即函数式接口声明。JDK 8 中有一系列的函数式编程辅类。其中一个就是
java.util.function.Supplier<T>
这个接口用于辅助获取结果。
Supplier<String> supplier = new Supplier<String>() {
@Override
public String get() {
return "newValue";
}
};
System.out.println(supplier.get());
老版本的匿名函数写法如上。但是 supplier 本身是一个函数式接口,所以我们可以很方便的简化代码:
Supplier<String> supplier = () -> "newValue";
System.out.println(supplier.get());
之前我也很少使用这个接口。知道后来在一个十分常见的使用场景中,发现使用简易封装的 supplier 可以大大减少样板业务代码的使用。
二 业务场景适配
业务场景 -> 接口缓存
![](https://img.haomeiwen.com/i4705286/33d33a29535b62d2.png)
在这样一个典型的缓存场景中,业务的样板代码会很繁琐,而且一旦业务中大量使用缓存的话,样板代码会占据很大的篇幅。
// 伪代码
value = redis.get(key)
if (null == value) {
data = mybatis.get(param)
redis.set(key, data)
return data
}
return value;
三 代码
这是一个在构造函数种传入了 supplier 的辅助类。redis 操作涉及到的 过期时间/时间单位 也封装到同一个构造函数。包含一个定义好的方法 get,其内容就是调用传入的 supplier 的 get 方法。
public class RedisSupplier <T> {
private int expire;
private TimeUnit timeUnit;
Supplier<T> supplier;
public int getExpire() {
return expire;
}
public void setExpire(int expire) {
this.expire = expire;
}
public TimeUnit getTimeUnit() {
return timeUnit;
}
public void setTimeUnit(TimeUnit timeUnit) {
this.timeUnit = timeUnit;
}
public Supplier<T> getSupplier() {
return supplier;
}
public void setSupplier(Supplier<T> supplier) {
this.supplier = supplier;
}
public RedisSupplier(int expire, TimeUnit timeUnit, Supplier<T> supplier) {
this.expire = expire;
this.timeUnit = timeUnit;
this.supplier = supplier;
}
public T get() {
return this.supplier.get();
}
}
用于模拟缓存使用场景的 cacheUtil 类,注意这个 get 方法,其中传入了前面定义好的 redisSupplier 类实例。get 方法调用的源头就是 supplier.get,之所以在 jdk 标准的函数上封装了一层,是因为我们需要更多的自定义参数(缓存时长设置)。
public class CacheUtil {
private static HashMap<String, Object> localCache = new HashMap<>();
public <T> T get(String key, RedisSupplier<T> redisSupplier) {
Object value = localCache.get(key);
if (Objects.isNull(value)) {
T result = redisSupplier.get();
this.set(key, result, redisSupplier.getExpire(), redisSupplier.getTimeUnit());
return result;
}
return (T) value;
}
public void set(String key, Object value, int expire, TimeUnit timeUnit) {
localCache.put(key, value);
}
}
前面着重强调的样板代码,基本上都被封装在了这个 cacheUtil 类的 get 方法中。省略了这部分的代码,我们业务代码的编写就会很便捷。
如下为使用示例:
public static void main(String[] args) {
RedisSupplier<String> redisSupplier = new RedisSupplier<>(1, TimeUnit.DAYS, () -> "valueB");
CacheUtil cacheUtil = new CacheUtil();
String result = cacheUtil.get("B", redisSupplier);
System.out.println(result);
}
supplier 函数定义了当缓存中没获取到 key-B 的值的时候,用于给这个 key-B 设置值的方法,我们直接设置为了 valueB。实际使用场景就可以替换为 mybatis 的数据持久层获取数据的操作。
网友评论