在实际项目中,我们经常会遇到需要使用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(); // 未知订单类型的默认行为
}
}
代码详解:
Dictionary<string, Action>将订单类型(字符串键)映射到对应的方法(Action值)。C#中的Action委托代表一个不返回值的方法(即void方法)。ProcessOrder()方法中,我们使用ContainsKey()检查订单类型是否存在于字典中。如果存在,我们调用相应的action方法。如果订单类型不存在,则调用UnknownOrder()方法。优势: