函数式接口的应用

48 阅读2分钟

场景:发放奖品时,不同类型奖品的发放方式不一样,但有部分业务操作是相同的,比如检查用户、扣减库存等,这时有几种写法都能实现逻辑,其中各有优缺点

  • if逻辑判断:随着奖品类型的增加,代码变得不利于管理
  • 抽象类:新增奖品类型时,只需要实现对应的抽象方法即可,这种业务耦合低容易理解,不过需要创建不同的实现类
  • 函数式接口:通过函数式接口,传递对应方法进去内部执行,这种适合于逻辑简单的操作,一旦逻辑复杂起来,也是不利于管理

第一个种:if判断

public class SendService {


    public void sendWechatReward(Long uid, Integer type, BigDecimal reward) {
        // 检查用户: 是否有效
        checkUser(uid);
        // 校验奖励是否有效: 重复发放等校验
        checkReward(uid, type);
        // 发放奖励: 调用微信接口
        invokeWechatReward(uid, reward);
        // 新增流水记录
        addRewardLog(uid, type, reward);
    }

    public void sendAlipayReward(Long uid, Integer type, BigDecimal reward) {
        // 检查用户: 是否有效
        checkUser(uid);
        // 校验奖励是否有效: 重复发放等校验
        checkReward(uid, type);
        // 发放奖励: 调用阿里接口
        invokeAlipayReward(uid, reward);
        // 新增流水记录
        addRewardLog(uid, type, reward);
    }

    public void sendReward(Long uid, Integer type, String platform, BigDecimal reward) {
        // 检查用户: 是否有效
        checkUser(uid);
        // 校验奖励是否有效: 重复发放等校验
        checkReward(uid, type);
        // 发放奖励: 调用阿里接口
        if (StringUtils.equals(platform, "alipay")) {
            invokeAlipayReward(uid, reward);
        } else if (StringUtils.equals(platform, "wechat")) {
            invokeWechatReward(uid, reward);
        }
        // 新增流水记录
        addRewardLog(uid, type, reward);
    }

    public static void main(String[] args) {
        rewardService.sendReward(1, 1, "alipay", BigDecimal.valueOf(10));
        rewardService.sendReward(1, 1, "wechat", BigDecimal.valueOf(10));
    }
}

第二个种:抽象类

public abstract class AbstractRewardService {

    public void sendReward(Long uid, Integer type, BigDecimal reward) {
        // 检查用户: 是否有效
        checkUser(uid);
        // 校验奖励是否有效: 重复发放等校验
        checkReward(uid, type);
        // 发放奖励
        invokerRemote(uid, type, reward);
        // 新增流水记录
        addRewardLog(uid, type, reward);
    }

    /**
     * 调用接口发放奖励
     */
    public abstract void invokerRemote(Long uid, Integer type, BigDecimal reward);
}
public class WechatRewardService extends AbstractRewardService {
    @Override
    public void invokerRemote(Long uid, Integer type, BigDecimal reward) {
        System.out.println("调用wechat接口");
    }

    public static void main(String[] args) {
        // 发放微信
        wechatRewardService.sendReward(1, 1, BigDecimal.valueOf(10));
        // 发放支付宝
        alipayRewardService.sendReward(1, 1, BigDecimal.valueOf(10));
    }
}

第三种:使用函数式将方法作为参数传递进去

public class InvokerService {

    public void sendReward(Long uid, Integer type, BigDecimal reward, Invoker invoker) {
        // 检查用户: 是否有效
        checkUser(uid);
        // 校验奖励是否有效: 重复发放等校验
        checkReward(uid, type);
        // 发放奖励
        invoker.invoker();
        // 新增流水记录
        addRewardLog(uid, type, reward);
    }

    public static void main(String[] args) {
        // 发放微信
        rewardService.sendReward(1, 1, BigDecimal.valueOf(1), () -> invokeWechatRemote());
        // 发放支付宝
        rewardService.sendReward(1, 1, BigDecimal.valueOf(1), () -> invokeAlipayRemote());
    }

}

@FunctionalInterface
interface Invoker {
    /**
     * 无参无返回值
     */
    void invoker();
}