考虑以下场景:
我想设计一个折扣计算器,计算出可应用于订单的折扣。有两种类型的订单:在线和店内。根据订单类型和订单总金额,折扣计算器计算折扣。
我用 C# 编程来演示该场景,但问题与语言无关。在下面的代码中,DiscountCalculator
类通过检查输入参数的实际类型来计算折扣。
我觉得在 GetDiscount
方法中检查 IOrder
参数的实际类型是代码味道;因为我隐藏了接口(interface) IOrder
后面的实现细节,所以我以某种方式开箱即用了本应隐藏的内容。
interface IOrder
{
int GetTotalPrice();
}
class InStoreOrder : IOrder
{
public int GetTotalPrice() { // returns the price of order }
}
class OnlineOrder : IOrder
{
public int GetTotalPrice() { // returns the price of order }
}
class DiscountCalculator
{
public int GetDiscount(IOrder order)
{
Type orderType = order.GetType();
if (orderType == typeof(OnlineOrder))
{
if (order.GetTotalPrice() < 100)
return 2;
else
return 5;
}
if (orderType == typeof(InStoreOrder))
{
if (order.GetTotalPrice() < 100)
return 3;
else
return 6;
}
else
throw new Exception("Unknown order type:" + orderType.Name);
}
}
有什么想法吗?
更新:
我真的很感谢大家在这方面的合作。所有的解决方案不仅具有启发性,而且还带来了一种优雅的方式。
顺便说一句,既然所有的答案都让我确信这个解决方案不好,我就在想 Abstract Factory
可能是一个不错的选择。为什么?因为我们正在处理一系列相关对象:Order
和 DiscountCalculator
。
像这样:
Factory f = new FactoryRepo ("Online");
IOrder order = f.CreateItem();
IDiscountCalculator discounter = f.CreateDiscountCalculator();
....
这样,我认为对于 future 的变化,正如@Dhruv Rai Puri 指出的那样,可以轻松应用装饰器模式。
有什么想法吗?
最佳答案
是的,检查输入参数的实际类型违背了使用接口(interface)的目的。更好的方法是像这样修改 IOrder 接口(interface)
interface IOrder
{
int GetTotalPrice();
int GetDiscount();
}
然后允许每个实现计算适当的折扣。完成此操作后,您可以将 DiscountCalculator 中的方法简化为
order.GetDiscount();
关于design-patterns - 使用接口(interface)然后检查实现类型是否不好?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32782193/