我在 SpringBoot 里埋的 “if else 炸弹”,被架构师用这三招拆了!

我在SpringBoot里埋的“if else炸弹”,被架构师用这三招拆了!

前几天我写的SpringBoot代码被架构师批了:整整200行的Service方法,里面全是if else嵌套,像极了我家那团缠在一起的耳机线。架构师边摇头边说:“你这是埋了个定时炸弹啊,以后维护的人得骂你!”

痛定思痛,我跟着架构师学了三招,成功把代码从“shi山”变成了“艺术品”。今天就把这些套路分享给大家,下次写if else之前,先想想这篇文章!

一、策略模式:把if else变成“查表法”

场景还原

我当时在写一个订单支付的逻辑,根据不同的支付方式(微信、支付宝、银联)做不同的处理:

public String payOrder(String paymentType, BigDecimal amount) {
    if ("WECHAT".equals(paymentType)) {
        // 微信支付逻辑:调用微信支付API,生成二维码...
        return "微信支付成功";
    } else if ("ALIPAY".equals(paymentType)) {
        // 支付宝支付逻辑:调用支付宝API,生成支付链接...
        return "支付宝支付成功";
    } else if ("UNIONPAY".equals(paymentType)) {
        // 银联支付逻辑:调用银联API...
        return "银联支付成功";
    } else {
        return "不支持的支付方式";
    }
}

架构师说:“这种代码每加一种支付方式,就得改一次if else,违反开闭原则!”他教我用策略模式改造:

改造后

  1. 定义支付策略接口:
public interface PaymentStrategy {
    String pay(BigDecimal amount);
}
  1. 为每种支付方式实现接口:
@Component("WECHAT")
public class WechatPaymentStrategy implements PaymentStrategy {
    @Override
    public String pay(BigDecimal amount) {
        return "微信支付成功";
    }
}

@Component("ALIPAY")
public class AlipayPaymentStrategy implements PaymentStrategy {
    @Override
    public String pay(BigDecimal amount) {
        return "支付宝支付成功";
    }
}
  1. 用Map“查表”代替if else:
@Service
public class OrderService {

    @Autowired
    private Map<String, PaymentStrategy> paymentStrategyMap;

    public String payOrder(String paymentType, BigDecimal amount) {
        PaymentStrategy strategy = paymentStrategyMap.get(paymentType);
        if (strategy == null) {
            return "不支持的支付方式";
        }
        return strategy.pay(amount);
    }
}

现在如果要加一种支付方式,只需要新增一个实现类并加上@Component注解,连OrderService都不用改!这就叫“对扩展开放,对修改关闭”,架构师的逼格果然不一样。

二、责任链模式:让请求“过五关斩六将”

场景还原

我又遇到一个用户注册的逻辑,要依次校验用户名、密码、邮箱格式,然后保存用户:

public void registerUser(User user) {
    if (user.getUsername() == null || user.getUsername().isEmpty()) {
        throw new IllegalArgumentException("用户名不能为空");
    }
    if (user.getPassword() == null || user.getPassword().length() < 6) {
        throw new IllegalArgumentException("密码长度不能小于6位");
    }
    if (user.getEmail() == null || !user.getEmail().matches("^[a-zA-Z0-9]+@[a-zA-Z0-9]+\\.[a-zA-Z]{2,}$")) {
        throw new IllegalArgumentException("邮箱格式不正确");
    }
    // 保存用户到数据库
    userRepository.save(user);
}

架构师又看不下去了:“万一以后要加个手机号校验,或者调整校验顺序,这代码不得乱成一锅粥?”他掏出了责任链模式:

改造后

  1. 定义处理器接口:
public interface UserValidator {
    void validate(User user) throws IllegalArgumentException;
    void setNextValidator(UserValidator nextValidator);
}
  1. 为每个校验规则创建处理器:
public class UsernameValidator implements UserValidator {
    private UserValidator nextValidator;

    @Override
    public void validate(User user) throws IllegalArgumentException {
        if (user.getUsername() == null || user.getUsername().isEmpty()) {
            throw new IllegalArgumentException("用户名不能为空");
        }
        if (nextValidator != null) {
            nextValidator.validate(user);
        }
    }

    @Override
    public void setNextValidator(UserValidator nextValidator) {
        this.nextValidator = nextValidator;
    }
}

// 类似的,创建PasswordValidator和EmailValidator
  1. 组装责任链:
@Service
public class UserService {

    public void registerUser(User user) {
        UserValidator usernameValidator = new UsernameValidator();
        UserValidator passwordValidator = new PasswordValidator();
        UserValidator emailValidator = new EmailValidator();

        usernameValidator.setNextValidator(passwordValidator);
        passwordValidator.setNextValidator(emailValidator);

        usernameValidator.validate(user);
        userRepository.save(user);
    }
}

现在如果要加个手机号校验,只需要新增一个PhoneValidator并加到链里,原来的代码完全不用动。这就像过安检,每个安检员只负责自己的那部分检查,查完后交给下一个,秩序井然。

三、枚举类:用“魔法表”替代复杂判断

场景还原

我写了个根据不同状态计算订单折扣的方法:

public BigDecimal calculateDiscount(Order order) {
    if (OrderStatus.NEW.equals(order.getStatus())) {
        return new BigDecimal("0.9"); // 新订单9折
    } else if (OrderStatus.PAID.equals(order.getStatus())) {
        return new BigDecimal("0.8"); // 已支付8折
    } else if (OrderStatus.SHIPPED.equals(order.getStatus())) {
        return new BigDecimal("0.7"); // 已发货7折
    } else if (OrderStatus.COMPLETED.equals(order.getStatus())) {
        return new BigDecimal("0.6"); // 已完成6折
    } else {
        return BigDecimal.ONE; // 其他情况不打折
    }
}

架构师说:“这种状态和折扣的对应关系,为什么不用枚举类?”

改造后

public enum OrderStatus {
    NEW("新订单", new BigDecimal("0.9")),
    PAID("已支付", new BigDecimal("0.8")),
    SHIPPED("已发货", new BigDecimal("0.7")),
    COMPLETED("已完成", new BigDecimal("0.6"));

    private final String description;
    private final BigDecimal discount;

    OrderStatus(String description, BigDecimal discount) {
        this.description = description;
        this.discount = discount;
    }

    public BigDecimal getDiscount() {
        return discount;
    }
}

// 现在计算折扣只需要一行代码
public BigDecimal calculateDiscount(Order order) {
    return order.getStatus() != null ? order.getStatus().getDiscount() : BigDecimal.ONE;
}

这就像把状态和折扣的对应关系写在一张“魔法表”里,需要的时候直接查表就行,代码简洁得让人想哭。

总结:告别“面条代码”的3个心法

  1. 遇到“类型判断”,优先想策略模式:把每种类型的处理逻辑封装成独立的策略类,用Map管理,避免if else膨胀。
  2. 遇到“步骤流程”,考虑责任链模式:把每个步骤的处理逻辑封装成处理器,连成一条链,方便增删改步骤。
  3. 遇到“固定映射”,用枚举类:把固定的状态-行为、参数-结果等映射关系放进枚举类,代码更清爽。

最后再分享个架构师的金句:“好的代码应该像一篇文章,而不是一堵if else墙。”下次写代码时,记得先想想这篇文章,说不定能少写几百行if else,多留时间摸鱼呢!
如果你是刚开始学习java,或者刚开始从事java行业,有很多的问题都可以关注微信公众号“java学长”,一个致力于打造免费指导学习java高薪就业的公益平台!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@佳瑞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值