You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Web API:用设计模式消除Controller中的If-Else分支

嘿,这个场景太适合用策略模式来重构了,既能摆脱那些缠人的if-else嵌套,还能让代码更易扩展和维护。另外咱们也可以用OOP的思路把RequestModel的行为封装起来,让控制器彻底和分支逻辑说拜拜。我给你一步步拆解:

1. 用策略模式替代If-Else:拆分业务逻辑

核心思路是把每种组合场景的业务逻辑封装成独立的策略类,然后通过一个“策略提供者”来匹配并执行对应逻辑。

第一步:定义策略接口

先给所有业务逻辑约定一个统一的接口:

public interface IInventoryStrategy
{
    // 判断当前策略是否匹配请求场景
    bool IsMatch(RequestModel model, int existingQty);
    // 执行对应业务逻辑
    void Execute(RequestModel model, int existingQty);
}

第二步:实现具体策略类

每种组合场景对应一个策略类,比如你提到的「现有库存小于请求数量且Owner为true」的场景:

public class OwnerTrueQtyLessStrategy : IInventoryStrategy
{
    public bool IsMatch(RequestModel model, int existingQty)
    {
        return existingQty < model.Quantity && model.Owner == true;
    }

    public void Execute(RequestModel model, int existingQty)
    {
        // 这里写原来第一个if块里的业务逻辑
        // 比如:更新库存、生成记录等
    }
}

再比如「现有库存等于请求数量」的场景:

public class QtyEqualStrategy : IInventoryStrategy
{
    public bool IsMatch(RequestModel model, int existingQty)
    {
        return existingQty == model.Quantity;
    }

    public void Execute(RequestModel model, int existingQty)
    {
        // 对应的业务逻辑,不用处理DoSplit和Owner的判断
    }
}

你可以按照这个方式,把所有if-else分支都拆成独立的策略类。

第三步:创建策略提供者

这个类负责管理所有策略,在运行时找到匹配的策略:

public class InventoryStrategyProvider
{
    private readonly IEnumerable<IInventoryStrategy> _strategies;

    // 借助ASP.NET Core的依赖注入,自动注入所有实现了IInventoryStrategy的类
    public InventoryStrategyProvider(IEnumerable<IInventoryStrategy> strategies)
    {
        _strategies = strategies;
    }

    public IInventoryStrategy GetMatchingStrategy(RequestModel model, int existingQty)
    {
        // 找到第一个匹配的策略
        var strategy = _strategies.FirstOrDefault(s => s.IsMatch(model, existingQty));
        if (strategy == null)
        {
            // 可以抛出自定义异常,或者返回一个默认策略处理未知场景
            throw new InvalidOperationException("No matching strategy found for the request");
        }
        return strategy;
    }
}
2. 优化RequestModel:用OOP封装判断逻辑

因为模型是从前端JS传过来的,我们可以给它加一些辅助方法,把分散的判断逻辑封装进去,让策略类的代码更简洁:

public class RequestModel 
{ 
    public string PartType { get; set; } 
    public int Quantity { get; set; } 
    public decimal UnitCost{ get; set; } 
    public bool? Owner { get; set; } 
    public bool? DoSplit { get; set; } 
    // 假设你原来的代码里有SerialId,不然GetInitialQuantity没法用
    public string SerialId { get; set; }

    // 封装判断逻辑,让代码更可读
    public bool IsOwnerTrue() => Owner.HasValue && Owner.Value;
    public bool IsOwnerFalse() => Owner.HasValue && !Owner.Value;
    public bool IsQtyGreaterThanExisting(int existingQty) => Quantity > existingQty;
    public bool IsQtyEqualExisting(int existingQty) => Quantity == existingQty;
    // 可以根据需求添加更多类似的封装方法
}

这样策略类的IsMatch方法就可以写成更清晰的形式:

public bool IsMatch(RequestModel model, int existingQty)
{
    return model.IsQtyGreaterThanExisting(existingQty) && model.IsOwnerTrue();
}
3. 控制器彻底消除分支

现在你的Post方法就变得超级干净,不需要任何if-else:

[HttpPost]
public IActionResult ProcessInventory([FromBody] RequestModel model)
{
    int existingQty = GetInitialQuantity(model.SerialId);
    
    // 找到匹配的策略并执行
    var strategy = _strategyProvider.GetMatchingStrategy(model, existingQty);
    strategy.Execute(model, existingQty);

    return Ok();
}
额外优化:处理默认场景

为了避免出现找不到策略的情况,你可以加一个默认策略,处理所有未被覆盖的场景:

public class DefaultInventoryStrategy : IInventoryStrategy
{
    public bool IsMatch(RequestModel model, int existingQty)
    {
        return true; // 匹配所有未被其他策略处理的情况
    }

    public void Execute(RequestModel model, int existingQty)
    {
        // 比如记录日志、返回友好错误提示等
    }
}

只要确保默认策略在所有策略中最后被匹配(比如注册DI时放在最后,或者给策略加优先级排序),就能兜底处理未知情况。

为什么这么做?
  • 可扩展性:以后新增组合逻辑,只需要加一个新的策略类,完全不用修改原有代码,符合开放封闭原则
  • 可维护性:每个策略类只处理一种场景,逻辑清晰,调试和修改都很方便
  • 解耦:控制器只负责接收请求、获取数据、调用策略,不处理具体业务逻辑,符合单一职责原则

内容的提问来源于stack exchange,提问作者Bharathg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:22:06