告别if/else地狱:从表驱动到设计模式的代码重构实战

news2026/5/22 3:59:34
1. 项目概述从“屎山”到“优雅”的代码重构之旅“优雅地优化掉这些多余的if/else”这几乎是每个有一定经验的开发者在接手或维护一个项目时内心最常响起的呐喊。我见过太多代码它们最初可能只是几个简单的条件判断但随着业务逻辑像藤蔓一样疯狂生长最终演变成了嵌套五六层、长达数百行的“if/else地狱”。每次新增一个需求都像是在这团乱麻上再打一个死结代码的可读性、可维护性和可测试性急剧下降最终成为团队里人人避之不及的“屎山”。这绝不是一个简单的语法问题它背后折射的是软件设计思想、抽象能力以及对代码“坏味道”的敏锐嗅觉。一个优雅的解决方案不仅仅是让代码看起来更简洁更重要的是建立一套清晰、可扩展的规则处理机制让未来的需求变更能够平滑地融入现有架构而不是继续堆砌条件分支。今天我们就来系统地拆解这个问题从最直观的代码“坏味道”识别到层层递进的重构策略再到结合设计模式的终极优雅方案。无论你是正在被满屏if/else困扰的开发者还是希望提前规避此类问题的架构师这篇文章都将为你提供一套完整的、可落地的“手术刀”。2. 核心思路从“条件驱动”到“行为驱动”的范式转变要优雅地优化if/else首先要理解其本质问题。泛滥的if/else通常意味着代码是“条件驱动”的程序流程被一系列散落在各处的、针对具体值的条件判断所控制。这种模式的弊端非常明显逻辑分散、职责不清、修改一处可能引发多处连锁反应。我们的优化目标是转向“行为驱动”或“数据驱动”的范式。核心思路是将“做什么”行为与“在什么条件下做”判断解耦。我们不再关注“如果类型是A则执行X如果是B则执行Y”而是建立一种映射关系或分发机制让程序能根据输入如类型自动找到对应的行为并执行。这就像从手动操作一个个开关升级为设置好自动化规则的系统。实现这一转变通常遵循一个由浅入深的重构路径守卫语句与提前返回处理简单的、边界或异常情况净化主逻辑流。表驱动法将条件与行为的映射关系抽取到数据结构如Map中用查表代替分支。策略模式当每个分支背后的行为逻辑复杂且独立时将其封装成独立的策略类。责任链模式当条件判断具有链式或优先级特性时将处理者连成一条链依次尝试。状态模式当对象的行为取决于其内部状态且状态转换频繁时将状态抽象为对象。下面我们就沿着这条路径结合具体代码示例一步步拆解如何实施。2.1 识别“坏味道”你的if/else是否需要优化不是所有的if/else都是坏的。简单的、非此即彼的判断如if (value null)是清晰且必要的。我们需要优化的是那些已经散发出“坏味道”的复杂条件逻辑。你可以通过以下特征来识别嵌套过深超过3层的嵌套会使代码路径难以追踪可读性极差。重复判断相同的条件判断逻辑在多个地方出现。分支过长每个分支内的代码行数很多职责混杂。频繁修改每当新增一种类型或状态就需要在现有的if/else块中插入新的分支违反了“开闭原则”。条件表达式复杂条件判断中掺杂了过多的逻辑运算难以一眼看懂其意图。当你发现代码具备上述特征时就是时候考虑重构了。3. 初级优化守卫语句与表驱动法3.1 守卫语句净化主逻辑流守卫语句Guard Clauses的核心思想是“尽早返回”。它将处理特殊情况如参数校验、边界条件、错误处理的逻辑放在函数开头一旦条件满足立即返回从而保证函数主体部分专注于核心的正常业务逻辑。这能有效减少嵌套让代码的“主干道”清晰可见。重构前示例public double calculateDiscount(Order order, Customer customer) { double discount 0.0; if (order ! null) { if (customer ! null) { if (customer.isVIP()) { discount 0.2; // VIP折扣 } else if (order.getAmount() 1000) { discount 0.1; // 大额订单折扣 } else { discount 0.05; // 普通折扣 } } else { throw new IllegalArgumentException(Customer cannot be null); } } else { throw new IllegalArgumentException(Order cannot be null); } return discount; }这段代码使用了典型的“箭头型”嵌套核心折扣逻辑被埋藏在三层if之下。重构后使用守卫语句public double calculateDiscount(Order order, Customer customer) { // 守卫语句尽早处理异常和边界情况 if (order null) { throw new IllegalArgumentException(Order cannot be null); } if (customer null) { throw new IllegalArgumentException(Customer cannot be null); } // 主逻辑变得清晰平坦 if (customer.isVIP()) { return 0.2; } if (order.getAmount() 1000) { return 0.1; } return 0.05; }实操心得守卫语句不仅减少了嵌套更重要的是明确了函数的“入口契约”。所有调用者都能从函数开头就知道哪些输入是非法的这比在深层嵌套中抛出异常要友好和清晰得多。这是一种成本极低但收益很高的重构手段应作为编写函数的习惯。3.2 表驱动法用数据代替逻辑分支当你的if/else主要是根据某个键值如状态码、类型枚举映射到不同的结果或简单行为时表驱动法是绝佳选择。其核心是将映射关系从代码逻辑转移到数据结构通常是Map中。场景根据用户等级返回对应的折扣力度和欢迎语。重构前public String getDiscountInfo(String userLevel) { if (普通会员.equals(userLevel)) { return 享受9.5折优惠; } else if (黄金会员.equals(userLevel)) { return 享受9折优惠生日双倍积分; } else if (铂金会员.equals(userLevel)) { return 享受8.5折优惠专属客服免运费; } else if (钻石会员.equals(userLevel)) { return 享受8折优惠所有特权线下活动邀请; } else { return 暂无优惠; } }每新增一个会员等级就要修改这个函数增加一个分支。重构后使用表驱动法// 1. 定义配置数据可以放在常量类、数据库或配置中心 private static final MapString, String DISCOUNT_MAP new HashMap(); static { DISCOUNT_MAP.put(普通会员, 享受9.5折优惠); DISCOUNT_MAP.put(黄金会员, 享受9折优惠生日双倍积分); DISCOUNT_MAP.put(铂金会员, 享受8.5折优惠专属客服免运费); DISCOUNT_MAP.put(钻石会员, 享受8折优惠所有特权线下活动邀请); } // 2. 业务方法变得极其简洁 public String getDiscountInfo(String userLevel) { return DISCOUNT_MAP.getOrDefault(userLevel, 暂无优惠); }进阶用法映射到行为如果每个分支对应的不是简单值而是一段需要执行的逻辑行为我们可以映射到Function、Runnable或自定义接口。// 定义行为接口 interface DiscountStrategy { double calculate(double originalPrice); } // 构建策略映射表 private static final MapString, DiscountStrategy STRATEGY_MAP new HashMap(); static { STRATEGY_MAP.put(普通会员, price - price * 0.95); STRATEGY_MAP.put(黄金会员, price - price * 0.90); STRATEGY_MAP.put(铂金会员, price - price * 0.85); } public double applyDiscount(String userLevel, double price) { DiscountStrategy strategy STRATEGY_MAP.get(userLevel); if (strategy ! null) { return strategy.calculate(price); } return price; // 默认无折扣 }注意事项表驱动法适用于条件判断相对静态、分支逻辑独立的场景。如果映射关系需要动态变化如从数据库加载只需将静态初始化块改为从数据源加载即可。它的优势在于将“配置”与“逻辑”分离修改配置无需改动代码符合开闭原则。4. 中级优化策略模式与工厂模式组合拳当每个分支背后的逻辑非常复杂不再是简单的一行代码或一个函数调用时表驱动法中的Lambda可能会变得臃肿。此时策略模式Strategy Pattern就该登场了。它将每一个算法或行为封装成一个独立的类使得它们可以相互替换让算法的变化独立于使用它的客户。4.1 策略模式实战订单折扣计算假设我们有一个电商系统需要根据不同的促销类型如满减、折扣、立减来计算订单最终价格。if/else版本会非常恐怖。步骤1定义策略接口public interface PromotionStrategy { /** * 计算促销后的价格 * param order 原始订单 * return 促销后价格 */ double applyPromotion(Order order); }步骤2实现具体策略// 满减策略 public class FullReductionStrategy implements PromotionStrategy { private double fullAmount; private double reductionAmount; public FullReductionStrategy(double fullAmount, double reductionAmount) { this.fullAmount fullAmount; this.reductionAmount reductionAmount; } Override public double applyPromotion(Order order) { double total order.getTotalAmount(); if (total fullAmount) { return total - reductionAmount; } return total; } } // 折扣策略 public class DiscountStrategy implements PromotionStrategy { private double discountRate; // 0.8 表示8折 public DiscountStrategy(double discountRate) { this.discountRate discountRate; } Override public double applyPromotion(Order order) { return order.getTotalAmount() * discountRate; } } // 立减策略 public class DirectReductionStrategy implements PromotionStrategy { private double reductionAmount; public DirectReductionStrategy(double reductionAmount) { this.reductionAmount reductionAmount; } Override public double applyPromotion(Order order) { return Math.max(0, order.getTotalAmount() - reductionAmount); } }步骤3消除if/else——结合工厂模式策略模式本身解决了行为封装的问题但如何创建策略对象呢这里通常会引入工厂模式或简单工厂来负责对象的创建从而将对象创建逻辑也从客户端代码中剥离。// 促销策略工厂 public class PromotionStrategyFactory { // 使用Map注册策略键可以是促销类型编码或名称 private static final MapString, PromotionStrategy STRATEGIES new HashMap(); static { // 这里可以从配置中心、数据库加载策略配置 STRATEGIES.put(FULL_REDUCTION_100_10, new FullReductionStrategy(100.0, 10.0)); STRATEGIES.put(DISCOUNT_0.8, new DiscountStrategy(0.8)); STRATEGIES.put(DIRECT_REDUCTION_20, new DirectReductionStrategy(20.0)); // 新增策略只需在这里注册无需修改其他代码 STRATEGIES.put(NEW_YEAR_SPECIAL, new SomeNewStrategy()); } // 获取策略可增加默认策略或空值处理 public static PromotionStrategy getStrategy(String promotionType) { PromotionStrategy strategy STRATEGIES.get(promotionType); if (strategy null) { throw new IllegalArgumentException(未知的促销类型: promotionType); } return strategy; } // 或者提供非受检版本返回默认策略无促销 public static PromotionStrategy getStrategyOrDefault(String promotionType) { return STRATEGIES.getOrDefault(promotionType, order - order.getTotalAmount()); } }步骤4客户端调用public class OrderService { public double calculateFinalPrice(Order order, String promotionType) { // 原来的if/else彻底消失只剩一行 PromotionStrategy strategy PromotionStrategyFactory.getStrategy(promotionType); return strategy.applyPromotion(order); } }核心优势现在当需要新增一种促销类型比如“第二件半价”时你只需要创建一个新的SecondHalfPriceStrategy类实现PromotionStrategy接口。在工厂类的静态初始化块或配置源中添加一条映射关系如STRATEGIES.put(SECOND_HALF, new SecondHalfPriceStrategy())。订单计算逻辑OrderService完全不需要修改这完美符合“对扩展开放对修改关闭”的开闭原则。整个系统的可维护性和可测试性都得到了质的提升。你可以轻松地为每个策略编写独立的单元测试Mock也变得更加简单。4.2 策略模式的选择时机与陷阱何时使用策略模式当系统中有多个类它们的区别仅仅在于行为算法不同时。当一个对象有很多行为并且这些行为在运行时需要动态切换时。当你不希望将复杂的、与算法相关的数据结构暴露给客户端时。需要避开的坑过度设计如果只有两三个简单的、几乎不会变的分支直接用if/else或表驱动法更合适。策略模式会引入额外的接口和类增加系统复杂度。策略膨胀如果策略类过多管理起来也会麻烦。可以考虑使用注解、Spring容器自动注册等更高级的管理方式。上下文信息传递策略接口的设计很关键。需要仔细考虑哪些参数应该通过接口方法传入。像上面的Order对象就包含了策略计算所需的所有上下文。避免设计出apply(int a, int b, String c, Date d...)这种参数冗长的方法。5. 高级优化责任链与状态模式应对复杂场景5.1 责任链模式处理链式或优先级审批责任链模式Chain of Responsibility将请求的发送者和接收者解耦让多个对象都有机会处理这个请求。这些对象连成一条链并沿着这条链传递请求直到有一个对象处理它为止。这非常适合用于有先后顺序、分级处理或审批流的场景。经典场景费用报销审批流程。不同金额的报销需要不同级别的领导审批。if/else地狱版public void approveExpense(Expense expense) { double amount expense.getAmount(); if (amount 1000) { teamLeader.approve(expense); } else if (amount 5000) { departmentManager.approve(expense); } else if (amount 20000) { financeDirector.approve(expense); } else { cfo.approve(expense); } }问题审批逻辑和审批人耦合在一起新增一个审批层级或调整金额阈值都需要修改这个方法。责任链模式重构步骤1定义处理者接口和抽象类// 处理者接口 public interface Approver { void setNext(Approver next); void handleRequest(Expense expense); } // 抽象处理者封装设置下一级和传递请求的通用逻辑 public abstract class AbstractApprover implements Approver { protected Approver next; protected String name; protected double approvalLimit; public AbstractApprover(String name, double approvalLimit) { this.name name; this.approvalLimit approvalLimit; } Override public void setNext(Approver next) { this.next next; } Override public void handleRequest(Expense expense) { if (expense.getAmount() approvalLimit) { // 当前处理者有权审批 System.out.println(name 审批了报销单金额 expense.getAmount()); expense.setApproved(true); } else if (next ! null) { // 传递给下一级 System.out.println(name 无权限审批转交上级。); next.handleRequest(expense); } else { // 链结束无人能批 System.out.println(报销单金额过高无人有权审批。); expense.setApproved(false); } } }步骤2实现具体处理者public class TeamLeader extends AbstractApprover { public TeamLeader() { super(组长, 1000); } } public class DepartmentManager extends AbstractApprover { public DepartmentManager() { super(部门经理, 5000); } } public class FinanceDirector extends AbstractApprover { public FinanceDirector() { super(财务总监, 20000); } } public class CFO extends AbstractApprover { public CFO() { super(首席财务官, Double.MAX_VALUE); // CFO可以审批任何金额 } }步骤3组装责任链并调用public class ApprovalChain { public static Approver getChain() { Approver teamLeader new TeamLeader(); Approver deptManager new DepartmentManager(); Approver financeDir new FinanceDirector(); Approver cfo new CFO(); // 组装链组长 - 部门经理 - 财务总监 - CFO teamLeader.setNext(deptManager); deptManager.setNext(financeDir); financeDir.setNext(cfo); return teamLeader; // 返回链头 } } // 客户端调用 public class ExpenseService { public void submitExpense(Expense expense) { Approver approvalChain ApprovalChain.getChain(); approvalChain.handleRequest(expense); // 后续根据expense.isApproved()处理 } }实操心得责任链模式将判断逻辑分散到了每个处理者内部handleRequest方法中的if (amount limit)。客户端完全不知道链上有谁也不关心审批顺序它只需要把请求丢给链头。要调整审批额度或增加一个“副总裁”审批环节只需要新建一个VicePresident类并在组装链时插入到合适位置即可ExpenseService的提交逻辑纹丝不动。这种解耦对于流程经常变化的业务系统来说价值巨大。5.2 状态模式管理复杂的状态转换状态模式State Pattern允许一个对象在其内部状态改变时改变它的行为对象看起来似乎修改了它的类。它主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况把状态的判断逻辑转移到表示不同状态的一系列类中。场景一个在线订单其状态有待支付、已支付、已发货、已收货、已完成、已取消。每个状态下订单能执行的操作不同如支付、发货、确认收货、取消。if/else灾难版public class Order { private String state; // “PENDING”, “PAID”, “SHIPPED”... public void pay() { if (PENDING.equals(state)) { state PAID; // ... 执行支付后逻辑 } else if (PAID.equals(state)) { throw new IllegalStateException(订单已支付无需重复支付); } else if (SHIPPED.equals(state)) { throw new IllegalStateException(订单已发货无法支付); } // ... 其他状态判断 } public void ship() { if (PAID.equals(state)) { state SHIPPED; // ... 执行发货逻辑 } else if (PENDING.equals(state)) { throw new IllegalStateException(订单未支付无法发货); } // ... 冗长的判断 } // cancel(), confirmReceipt() 等方法类似充斥着if/else }每增加一个状态或一个操作都需要在所有相关方法里添加分支极易出错。状态模式重构步骤1定义状态接口public interface OrderState { void pay(Order order); void ship(Order order); void cancel(Order order); void confirmReceipt(Order order); }步骤2实现各个具体状态类// 待支付状态 public class PendingState implements OrderState { Override public void pay(Order order) { System.out.println(支付成功); order.setState(new PaidState()); // 状态转移 // ... 其他支付成功后的业务逻辑 } Override public void ship(Order order) { throw new IllegalStateException(待支付订单不能发货); } Override public void cancel(Order order) { System.out.println(订单已取消); order.setState(new CancelledState()); } Override public void confirmReceipt(Order order) { throw new IllegalStateException(待支付订单不能确认收货); } } // 已支付状态 public class PaidState implements OrderState { Override public void pay(Order order) { throw new IllegalStateException(订单已支付无需重复支付); } Override public void ship(Order order) { System.out.println(商品已发货); order.setState(new ShippedState()); } Override public void cancel(Order order) { // 已支付订单取消可能需要走退款流程 System.out.println(订单取消发起退款流程); order.setState(new CancelledState()); } Override public void confirmReceipt(Order order) { throw new IllegalStateException(订单未发货不能确认收货); } } // ... 实现ShippedState, DeliveredState, CompletedState, CancelledState步骤3修改Order类委托给状态对象public class Order { private OrderState state; public Order() { this.state new PendingState(); // 初始状态 } // 设置状态包内可见或通过特定方法修改 void setState(OrderState state) { this.state state; } // 所有行为都委托给当前状态对象 public void pay() { state.pay(this); } public void ship() { state.ship(this); } public void cancel() { state.cancel(this); } public void confirmReceipt() { state.confirmReceipt(this); } }核心优势状态模式将特定状态下的所有行为局部化封装在对应的状态类中并且将状态转换规则也分布到了各个状态类里如PendingState.pay()方法中将状态设置为PaidState。这样一来Order类变得极其简洁稳定它不再包含任何状态判断逻辑。新增状态或行为变得容易。要增加一个“退款中”状态只需新建一个RefundingState类并修改相关状态类的转换逻辑如从PaidState.cancel()转换到RefundingState而Order类的核心结构无需变动。符合单一职责原则每个状态类只负责自己状态下的行为。也符合开闭原则对状态转换逻辑的修改是封闭的在状态类内部对新增状态是开放的。注意事项状态模式可能会产生大量的状态类对于状态数量有限且转换逻辑复杂的场景如工作流引擎、游戏角色状态机非常适用但对于状态简单且固定的场景可能会显得“杀鸡用牛刀”。6. 实战中的组合拳与边界情况处理在实际项目中我们很少只使用单一模式。更多时候需要根据业务场景灵活组合上述方法。6.1 策略模式 工厂模式 配置文件这是企业级应用中最常见的组合。我们将策略的具体实现和映射关系完全外置到配置文件如Spring的ComponentService注解或数据库配置表实现运行时动态加载。示例基于Spring的策略模式// 1. 策略接口 public interface NotificationStrategy { void send(String message, String target); String getType(); } // 2. 具体策略使用Component注解并标识类型 Component public class EmailNotificationStrategy implements NotificationStrategy { Override public void send(String message, String email) { // 发送邮件逻辑 System.out.println(发送邮件到 email : message); } Override public String getType() { return EMAIL; } } Component public class SmsNotificationStrategy implements NotificationStrategy { Override public void send(String message, String phone) { // 发送短信逻辑 System.out.println(发送短信到 phone : message); } Override public String getType() { return SMS; } } Component public class PushNotificationStrategy implements NotificationStrategy { Override public void send(String message, String userId) { // 发送推送逻辑 System.out.println(向用户 userId 发送推送: message); } Override public String getType() { return PUSH; } } // 3. 策略工厂自动收集所有策略 Service public class NotificationStrategyFactory { private final MapString, NotificationStrategy strategyMap new HashMap(); // 通过构造器注入所有NotificationStrategy的实现 Autowired public NotificationStrategyFactory(ListNotificationStrategy strategies) { for (NotificationStrategy strategy : strategies) { strategyMap.put(strategy.getType(), strategy); } } public NotificationStrategy getStrategy(String type) { NotificationStrategy strategy strategyMap.get(type); if (strategy null) { throw new IllegalArgumentException(Unsupported notification type: type); } return strategy; } } // 4. 业务服务类 Service public class NotificationService { Autowired private NotificationStrategyFactory factory; public void notifyUser(String type, String message, String target) { NotificationStrategy strategy factory.getStrategy(type); strategy.send(message, target); } }这种方式的威力在于当你需要新增一种通知方式比如“企业微信机器人”你只需要创建一个新的WechatRobotNotificationStrategy类实现NotificationStrategy接口并用Component注解。实现其send方法和getType方法。无需修改NotificationStrategyFactory和NotificationService的任何一行代码Spring的依赖注入机制会自动将新策略加入到工厂的Map中。这实现了极致的解耦和可扩展性。6.2 处理“其他/默认”情况在优化if/else时我们经常会遇到一个分支是“其他所有情况”或“默认情况”。在表驱动法或策略模式中需要妥善处理。表驱动法使用Map.getOrDefault(key, defaultValue)或提前在Map中放入一个“DEFAULT”键。策略模式可以定义一个DefaultStrategy或FallbackStrategy并在工厂的getStrategy方法中当找不到对应策略时返回它。责任链模式链的末尾可以放置一个DefaultHandler或TerminalHandler用于处理前面所有处理者都无法处理的请求。关键在于要将“默认行为”也作为一种明确的、可管理的策略而不是隐藏在else块中的一段模糊逻辑。6.3 性能考量反射与枚举的权衡有时为了极致解耦有人会使用反射Reflection来根据类名动态创建策略对象。这种方式提供了最大的灵活性策略类可以来自外部Jar包但会带来一定的性能开销和类型安全风险。// 谨慎使用基于反射的简单工厂 public class ReflectiveStrategyFactory { private static final String STRATEGY_PACKAGE com.example.strategy.; public static PromotionStrategy createStrategy(String strategyName) { try { Class? clazz Class.forName(STRATEGY_PACKAGE strategyName Strategy); return (PromotionStrategy) clazz.newInstance(); } catch (Exception e) { throw new RuntimeException(Failed to create strategy: strategyName, e); } } }建议在绝大多数应用场景下基于Map注册的工厂模式性能足够好且类型安全。除非你的系统需要支持真正的热插拔如插件系统否则应优先避免使用反射。另一种折中方案是使用枚举Enum来定义策略将行为内嵌在枚举常量中兼具类型安全和一定的灵活性。7. 重构心法与实操建议看到这里你可能已经掌握了多种武器。但在实际动手重构时还有一些更重要的心法。1. 小步快跑安全第一不要试图一次性将整个庞大的“屎山”全部重构。优先选择一处逻辑清晰但分支较多的“小山头”进行试点。每次重构后立即运行完整的单元测试和集成测试确保没有破坏现有功能。版本控制系统如Git是你的安全网大胆尝试不行就回退。2. 先写测试再重构这是重构的黄金法则。在动手修改代码之前先为你要重构的方法或类编写一套全面的单元测试。这些测试将定义代码的“正确行为”。重构过程中不断运行这些测试它们会像雷达一样告诉你是否引入了错误。3. 识别并抽取“变化点”仔细审视你的if/else代码块问自己未来最可能变化的是什么是增加新的类型还是修改某个分支的计算逻辑将这个“变化点”识别出来并将其封装起来。这就是软件设计的核心——封装变化。4. 命名是设计的一部分无论是策略类、状态类还是处理者类一个好的名字至关重要。名字应该清晰地表达其职责例如FullReductionStrategy比PromotionTypeA好得多PendingState比State1好得多。好的命名本身就是最好的文档。5. 权衡过度设计与设计不足这是一个艺术。如果业务规则极其稳定且if/else只有两三层强行套用设计模式可能是过度设计反而增加了复杂度。反之如果业务规则频繁变动或者分支逻辑已经复杂到难以测试和理解那么引入适当的设计模式就是必要的投资。一个简单的判断标准是当你发现增加一个新需求时感到痛苦需要修改多处、容易出错那就是需要重构的信号。6. 团队共识与代码规范个人的重构可能因为团队不理解而遭到抵制或后续被改坏。在重构前后与团队成员充分沟通解释为什么这么做可维护性、可测试性、降低缺陷率并争取将好的模式写入团队的代码规范。例如可以约定“当出现超过3个以上的同类条件分支时应考虑使用策略模式或表驱动法进行重构。”优雅地优化if/else远不止是让代码看起来更漂亮。它是一场关于如何编写易于理解、易于修改、易于测试的代码的思维训练。从识别代码的“坏味道”开始到熟练运用守卫语句、表驱动法、策略模式、责任链、状态模式等工具最终目的是构建一个健壮、灵活、能够从容应对需求变化的软件系统。这条路没有终点每一次对冗余if/else的成功重构都是你作为软件工程师专业能力的一次扎实提升。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2629901.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…