美文网首页
函数式编程-Supplier 的使用

函数式编程-Supplier 的使用

作者: 柯基去哪了 | 来源:发表于2020-06-30 15:11 被阅读0次

一 接口简单使用

在 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 可以大大减少样板业务代码的使用。

二 业务场景适配

业务场景 -> 接口缓存

image.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 的数据持久层获取数据的操作。

相关文章

网友评论

      本文标题:函数式编程-Supplier 的使用

      本文链接:https://www.haomeiwen.com/subject/ycjxqktx.html