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