【设计优化】卫语句、策略模式、状态模式

在写业务代码时,可能出现多层 if / else ,通常意味着以下问题之一或并存:

1.分支条件复杂、可读性差

2.业务规则易变、修改成本高

3.单一方法承担过多职责
卫语句、策略模式、状态模式正是针对不同"分支复杂性来源"而采用的三种典型重构手段。

一.卫语句

1.适用场景
"不满足条件就立即返回 / 抛异常"

适合用于:参数校验,前置条件校验,明显的异常路径,早退出逻辑

典型特征:if 之间没有状态变化,只是为了过滤非法情况,分支不代表不同业务策略

2.原始代码

csharp 复制代码
public decimal CalculatePrice(Order order)
{
    if (order != null)
    {
        if (order.Items != null && order.Items.Count > 0)
        {
            if (!order.IsCanceled)
            {
                return order.Items.Sum(x => x.Price);
            }
        }
    }
    return 0;
}

3.卫语句重构

csharp 复制代码
public decimal CalculatePrice(Order order)
{
    if (order == null) return 0;
    if (order.Items == null || order.Items.Count == 0) return 0;
    if (order.IsCanceled) return 0;

    return order.Items.Sum(x => x.Price);
}

4.优缺点

  • 极低改造成本
  • 可读性显著提升
  • 非常适合方法开头
  • 不能解决真正的业务分支爆炸
  • 不适合"不同规则 / 不同行为"的分支

二、策略模式(Strategy Pattern)

  1. 适用场景
    "同一件事,不同算法 / 不同规则"

判断标准:if / else 中每个分支:都是在"做同一件事",但实现逻辑不同,业务规则未来可能扩展

典型示例:价格计算,折扣规则,运费计算,权限校验规则

  1. 原始 if / else 示例
csharp 复制代码
public decimal CalculateDiscount(Order order)
{
    if (order.CustomerType == CustomerType.Vip)
        return order.Total * 0.8m;
    else if (order.CustomerType == CustomerType.Normal)
        return order.Total * 0.9m;
    else if (order.CustomerType == CustomerType.New)
        return order.Total;
    else
        return order.Total;
}
  1. 使用策略模式
csharp 复制代码
//① 抽象策略接口
public interface IDiscountStrategy
{
    decimal Calculate(Order order);
}
//② 具体策略实现
public class VipDiscountStrategy : IDiscountStrategy
{
    public decimal Calculate(Order order) => order.Total * 0.8m;
}

public class NormalDiscountStrategy : IDiscountStrategy
{
    public decimal Calculate(Order order) => order.Total * 0.9m;
}

public class NewCustomerDiscountStrategy : IDiscountStrategy
{
    public decimal Calculate(Order order) => order.Total;
}
//③ 策略选择(替代 if / else)
public class DiscountStrategyFactory
{
    private static readonly Dictionary<CustomerType, IDiscountStrategy> _strategies =
        new()
        {
            { CustomerType.Vip, new VipDiscountStrategy() },
            { CustomerType.Normal, new NormalDiscountStrategy() },
            { CustomerType.New, new NewCustomerDiscountStrategy() }
        };

    public static IDiscountStrategy Get(CustomerType type)
        => _strategies[type];
}
//④ 调用
var strategy = DiscountStrategyFactory.Get(order.CustomerType);
var discount = strategy.Calculate(order);
  1. 优缺点
  • 可扩展性极强
  • 每个策略逻辑清晰
  • 易测试、易维护
  • 类数量增加
  • 初期显得"设计偏重"
  • 需要额外的策略选择机制

三、状态模式(State Pattern)

  1. 适用场景
    "对象行为随状态变化而变化"

判断标准:if / else 依据的是 当前状态,同一方法在不同状态下行为不同,状态之间存在流转关系

典型示例:订单状态(新建 / 已支付 / 已发货 / 已取消),工作流,审批流程,设备状态(开机 / 关机 / 待机)

  1. 原始 if / else 示例
csharp 复制代码
public void Pay(Order order)
{
    if (order.Status == OrderStatus.Created)
    {
        order.Status = OrderStatus.Paid;
    }
    else if (order.Status == OrderStatus.Paid)
    {
        throw new Exception("订单已支付");
    }
    else if (order.Status == OrderStatus.Canceled)
    {
        throw new Exception("订单已取消");
    }
}
  1. 使用状态模式
csharp 复制代码
//① 状态接口
public interface IOrderState
{
    void Pay(OrderContext context);
}
//② 状态上下文
public class OrderContext
{
    public IOrderState State { get; set; }

    public void Pay()
    {
        State.Pay(this);
    }
}
//③ 具体状态
public class CreatedState : IOrderState
{
    public void Pay(OrderContext context)
    {
        context.State = new PaidState();
    }
}

public class PaidState : IOrderState
{
    public void Pay(OrderContext context)
    {
        throw new InvalidOperationException("订单已支付");
    }
}

public class CanceledState : IOrderState
{
    public void Pay(OrderContext context)
    {
        throw new InvalidOperationException("订单已取消");
    }
}
  1. 优缺点
  • 彻底消除状态判断
  • 状态逻辑高度内聚
  • 对复杂流程极友好
  • 类数量显著增加
  • 不适合简单状态
  • 初学者理解成本高

四、三者核心对比总结

维度 卫语句 策略模式 状态模式
解决什么问题 前置校验、异常路径 不同算法/规则 状态驱动行为
是否消除 if ❌ ✅ ✅
是否面向对象 否 是 是
类数量 不变 增加 大量增加
是否有状态流转 无 无 有
扩展性 低 高 高
使用成本 极低 中 高

完结撒花~

相关推荐
lank_M21 小时前
抠图换深色背景有白边?先分清直通和预乘alpha
图像处理·人工智能·计算机视觉·状态模式
弹简特21 小时前
【Java项目-企悦抽】17-抽奖模块02-抽奖接口实现
java·开发语言·状态模式·springboot
我是你的开心果7781 天前
ai全栈软件开发学习day27
人工智能·学习·状态模式
弹简特2 天前
【Java项目-企悦抽】16-抽奖模块01-获取活动完整信息接口实现
java·开发语言·状态模式·springboot
蜗牛互联网2 天前
Computer Use公共预览的安全设计:应用、动作与数据三维门禁
java·人工智能·后端·安全·策略模式
今年下半年3 天前
【Spring Boot】多种存储文件(FastDFS / MinIO / 阿里云 OSS)接入设计说明(附源码)
spring boot·分布式·中间件·简单工厂模式·策略模式
幽络源小助理4 天前
WordPress REST API 深度实战:从自定义端点到 Headless CMS 架构全拆解
架构·状态模式
牧瀬クリスだ6 天前
Spring统一功能处理
java·spring boot·spring·状态模式
Zkaisen6 天前
M4(Apple Silicon)· CVE-2020-13920 抓管理员密码 完整操作指南
策略模式
加载力科技7 天前
硬盘咔咔响是坏盘信号!赶在数据丢失前克隆换盘:不重装系统、不丢文件
windows·嵌入式硬件·系统安全·策略模式·命令模式·硬盘