【发布时间】:2021-04-22 10:33:08
【问题描述】:
我想避免使用处理特定情况的“if”和“switch”语句,而是采用更通用的方法。
要求: 根据下面详述的一些要求,订单的状态可能被确定为“已确认”、“已关闭”或“需要授权”。
输入:
IsRushOrder: bool
OrderType: Enum (Repair, Hire)
IsNewCustomer: bool
IsLargeOrder: bool
输出:
OrderStatus: Enum (Confirmed, Closed, AuthorisationRequired)
要求(按从上到下的优先顺序):
-Large repair orders for new customers should be closed
-Large rush hire orders should always be closed
-Large repair orders always require authorisation
-All rush orders for new customers always require authorisation
-All other orders should be confirmed
================================================ =============================
用 IF 语句避免明显的答案
这违反了SOLID原则的O。我相信有比添加大量 IF 语句更好的方法来做到这一点
public IOrder GetOrder(OrderInput orderInput)
{
// Apply rules based on the priority
if (orderInput.IsLargeOrder == true && orderInput.OrderType == OrderTypeEnum.Repair && orderInput.IsNewCustomer == true)
{
return new LargeRepairNewCustomerOrder();
}
if (orderInput.IsLargeOrder == true && orderInput.OrderType == OrderTypeEnum.Hire && orderInput.IsRushOrder == true)
{
return new LargeRushHireOrder();
}
if (orderInput.IsLargeOrder == true && orderInput.OrderType == OrderTypeEnum.Repair)
{
return new LargeRepairOrder();
}
if (orderInput.IsRushOrder == true && orderInput.IsNewCustomer == true)
{
return new AllRushNewCustomerOrder();
}
return new AllOtherOrders();
}
我可以想到的一种不使用 IF 实现的方法是在集合中填充 OrderStatus 并使用 LINQ 进行查询 随着我们添加更多状态,这个实现会很快变得复杂。
public class OrderStatusAnalyzer
{
protected static List<OrderStatus> OrderStatuses;
public OrderStatusAnalyzer()
{
OrderStatuses = OrderStatusCollection.Get();
}
public string GetOrderStatusTypeByOrderInput(OrderInput orderInput)
{
var orderStatusTypes = from orderStatus in OrderStatuses
where orderStatus.IsNewCustomer == orderInput.IsNewCustomer
&& orderStatus.IsLargeOrder == orderInput.IsLargeOrder
&& orderStatus.IsRushOrder == orderInput.IsRushOrder
&& orderStatus.OrderType == orderInput.OrderType
orderby orderStatus.Priority ascending
select orderStatus.OrderStatusType;
var statusTypesList = orderStatusTypes.ToList();
var orderStatusType = !statusTypesList.Any() ? "VehicleRepairOrder.Order.AllOtherOrders" : statusTypesList[0];
return orderStatusType;
}
}
public static class OrderStatusCollection
{
public static List<OrderStatus> Get()
{
// Note:
// 1) If we have to avoid referencing null, then we can populate the data with probabilities. Populating data with probabilities will become hard Maintain as we add more status
// 2) this is also violating O(Open for extension and closed for modification) of SOLID principle
// 3) instead of passing null, if you pass actual unit test will fail
var orderStatuses = new List<OrderStatus>
{
new OrderStatus
{
IsLargeOrder = true, IsNewCustomer = true, OrderType = OrderTypeEnum.Repair,
IsRushOrder = null,
Priority = 1, OrderStatusType = "VehicleRepairOrder.Order.LargeRepairNewCustomerOrder"
},
new OrderStatus
{
IsLargeOrder = true, IsNewCustomer = null, OrderType = OrderTypeEnum.Hire, IsRushOrder = true,
Priority = 2, OrderStatusType = "VehicleRepairOrder.Order.LargeRushHireOrder"
},
new OrderStatus
{
IsLargeOrder = true, IsNewCustomer = null, OrderType = OrderTypeEnum.Repair,
IsRushOrder = null,
Priority = 3, OrderStatusType = "VehicleRepairOrder.Order.LargeRepairOrder"
},
new OrderStatus
{
IsLargeOrder = null, IsNewCustomer = true, OrderType = OrderTypeEnum.Any, IsRushOrder = true,
Priority = 4, OrderStatusType = "VehicleRepairOrder.Order.AllRushNewCustomerOrder"
},
};
return orderStatuses;
}
}
【问题讨论】:
-
您需要一个字典或哈希方法来为不同的组合创建一个键。
-
我并不完全理解这个问题。你说输出应该是
Enum (Confirmed, Closed, AuthorisationRequired),但是你的代码输出了一个字符串比如"VehicleRepairOrder.Order.AllRushNewCustomerOrder" -
为什么没有ifs?如果您有 4 个 if,就像您在问题中陈述了您的要求,那么您将拥有一个易于阅读且易于使用调试器逐步完成的代码,以防出现问题。
-
@Canton7 我没有把所有的代码都放在那里我拿那个字符串并使用反射来识别类
-
@someBody 这违反了 SOLID 的 O 原则。我相信有比添加大量 IF 语句更好的方法
标签: c# design-patterns coding-style factory-pattern strategy-pattern