我在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,违反开闭原则!”他教我用策略模式改造:
改造后
- 定义支付策略接口:
public interface PaymentStrategy {
String pay(BigDecimal amount);
}
- 为每种支付方式实现接口:
@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 "支付宝支付成功";
}
}
- 用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);
}
架构师又看不下去了:“万一以后要加个手机号校验,或者调整校验顺序,这代码不得乱成一锅粥?”他掏出了责任链模式:
改造后
- 定义处理器接口:
public interface UserValidator {
void validate(User user) throws IllegalArgumentException;
void setNextValidator(UserValidator nextValidator);
}
- 为每个校验规则创建处理器:
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
- 组装责任链:
@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个心法
- 遇到“类型判断”,优先想策略模式:把每种类型的处理逻辑封装成独立的策略类,用Map管理,避免if else膨胀。
- 遇到“步骤流程”,考虑责任链模式:把每个步骤的处理逻辑封装成处理器,连成一条链,方便增删改步骤。
- 遇到“固定映射”,用枚举类:把固定的状态-行为、参数-结果等映射关系放进枚举类,代码更清爽。
最后再分享个架构师的金句:“好的代码应该像一篇文章,而不是一堵if else墙。”下次写代码时,记得先想想这篇文章,说不定能少写几百行if else,多留时间摸鱼呢!
如果你是刚开始学习java,或者刚开始从事java行业,有很多的问题都可以关注微信公众号“java学长”,一个致力于打造免费指导学习java高薪就业的公益平台!