告别臃肿Switch Case!用字典+委托实现优雅的业务逻辑分发

作者:微信公众号:【架构师老卢】
9-23 13:42
2

在实际项目中,我们经常会遇到需要使用switch case的情况,而这些switch语句会随着时间推移不断增长,变得难以管理。

让我们先理解问题 考虑以下代码:

using System;

class Program
{
    static void ProcessOrder(string orderType)
    {
        switch (orderType)
        {
            case "NEW_ORDER":
                Console.WriteLine("Processing new order.");
                // 新订单逻辑
                break;

            case "CANCEL_ORDER":
                Console.WriteLine("Cancelling order.");
                // 取消订单逻辑
                break;

            case "SHIPPING":
                Console.WriteLine("Shipping order.");
                // 发货逻辑
                break;

            case "DELIVERED":
                Console.WriteLine("Order delivered.");
                // 交付完成逻辑
                break;

            default:
                Console.WriteLine("Unknown order type.");
                break;
        }
    }

    static void Main(string[] args)
    {
        ProcessOrder("NEW_ORDER");
    }
}

违反SOLID原则: a. 庞大的switch语句很难遵循SOLID设计原则中的单一职责原则(SRP)和开闭原则(OCP)。这些原则指出:

b. 一个类应该只有一个修改原因(SRP),并且 一个类应该对扩展开放,对修改关闭(OCP)。 如果你通过添加新的case来修改switch语句,就违反了这两个原则。

2. 维护性问题:

当向switch添加新case时,我们必须更新代码,单个函数中的代码行数会增加,这将难以维护。

3. 代码可读性和可测试性

大量的switch语句会使代码更难阅读和测试。switch块中的每个case可能包含多行代码,包括业务逻辑、副作用和错误处理。这种复杂性使得单元测试变得困难,因为很难隔离与每个case相关的独立行为。

用字典+委托来优化 我们将用字典替换switch语句,其中每个键代表一个订单类型,值是一个委托或处理该订单类型逻辑的方法。

考虑以下代码:

class Program
{
    // 为每种订单类型定义方法
    static void NewOrder()
    {
        Console.WriteLine("Processing new order.");
        // 新订单逻辑
    }

    static void CancelOrder()
    {
        Console.WriteLine("Cancelling order.");
        // 取消订单逻辑
    }

    static void Shipping()
    {
        Console.WriteLine("Shipping order.");
        // 发货逻辑
    }

    static void Delivered()
    {
        Console.WriteLine("Order delivered.");
        // 交付完成逻辑
    }

    static void UnknownOrder()
    {
        Console.WriteLine("Unknown order type.");
    }
}

这里我们定义了需要在switch case中执行的Action方法。

为switch case定义字典代码:

static void Main(string[] args)
{
    // 定义将订单类型映射到对应方法的字典
    Dictionary<string, Action> orderActions = new Dictionary<string, Action>
    {
        { "NEW_ORDER", NewOrder },
        { "CANCEL_ORDER", CancelOrder },
        { "SHIPPING", Shipping },
        { "DELIVERED", Delivered }
    };

    // 使用示例
    ProcessOrder(orderActions, "NEW_ORDER");
    ProcessOrder(orderActions, "CANCEL_ORDER");
    ProcessOrder(orderActions, "UNKNOWN_ORDER");
}

static void ProcessOrder(Dictionary<string, Action> orderActions, string orderType)
{
    // 检查订单类型是否存在于字典中并执行相应操作
    if (orderActions.ContainsKey(orderType))
    {
        orderActions[orderType]();  // 调用相应方法
    }
    else
    {
        UnknownOrder();  // 未知订单类型的默认行为
    }
}

代码详解:

  • Action字典:使用Dictionary<string, Action>将订单类型(字符串键)映射到对应的方法(Action值)。C#中的Action委托代表一个不返回值的方法(即void方法)。
  • 订单处理:在ProcessOrder()方法中,我们使用ContainsKey()检查订单类型是否存在于字典中。如果存在,我们调用相应的action方法。如果订单类型不存在,则调用UnknownOrder()方法。

优势:

  • 可扩展性:只需添加新方法并更新字典即可轻松添加新订单类型。无需修改复杂的switch语句。
  • 可读性和可维护性:代码更有组织性,每种订单类型都由专用方法处理。
相关留言评论
昵称:
邮箱:
阅读排行