在这种情况下使用多态性优于枚举有什么好处吗?

Is there any benefit about using Polymorphism over Enum in this scenario?

场景

我正在创建动态查询生成器以发送到另一个组件(报表生成器)。

查询的某些部分有占位符。例如:

SELECT DISTINCT ID, NAME AS VALUE FROM EVENTS
WHERE {{ESTABLISHMENTFILTER.ID}} IS NULL OR ESTABLISHMENT_ID =   {{ESTABLISHMENTFILTER.ID}}

where 子句中要替换的数据可以是 Integer、String、Date,每个都有不同的行为(例如:在字符串大小写的值周围包含单引号)。

我的第一个方法是创建一个枚举:

public enum FilterType
{
    Integer,
    String
}

并像这样使用它(例如在业务层)

switch (filter.Type)
{
   case FilterType.Integer:
        //Do replace logic for an integer
        break;
   case FilterType.String:
        //Do replace logic for a string
        break;
   default:
        break;
}

我也在将 SOLID 原则应用到我的代码中,我发现这可能会破坏 OCP。所以我重构为使用基数 class

public abstract class FilterType
{
    public abstract string Replace(string baseString, string oldValue, string newValue);
}

并且每个类型都有自己的实现:

public class FilterTypeInteger : FilterType
{
    public override string Replace(string baseString,string oldValue, string newValue)
    {
        //Do logic to replace for an Integer type
    }
}

问题

SOLID 解决方案适用于我的测试,但在生产代码中,数据库中有一个 int 列来确定类型。所以我基本上是将 'switch-case' 逻辑转移到数据层,它必须检查此列以实例化正确的 FilterType (下面的代码是伪代码,因为我还没有实现它):

    if (dataReader["FILTERTYPE"] == 1)
        filter.Type = new FilterTypeInteger();
    else if (dataReader["FILTERTYPE"] == 2)
        filter.Type = new FilterTypeString();

问题

1) 上面实现'if-else'逻辑的方法是否破坏了OCP?因为如果创建了一个新的Type,就必须实现一个新的else子句
2) 是否有另一种方法可以在不使用 switch ou if-else 子句的情况下将 SOLID OCP 原则同时应用于数据库和业务代码?

Replacing conditional with polymorphysim 将确保决策只需要发生一次,所以这可能是个好主意。如果您在某些时候对每种类型有额外的专门操作,那么它们应该很容易实现。

现在,为了创建具体类型,您可以将此逻辑封装在工厂中。在最简单的形式中,工厂将是一个带有大量 switch 语句的静态工厂。它不遵守 OCP,但在大多数情况下它仍然是一个可以接受的设计。

但是,如果您希望通过设计在运行时实现可扩展,那将无法实现,您需要引入一种允许在运行时 discover/register 新类型的方法。

这可以通过多种方式完成,但一个例子是在工厂上有一个允许您注册新类型的方法。

例如

filterTypeFactory.RegisterFilter(1, typeof(FilterTypeInteger));

无论如何,在您拥有并构建自己的 SQL 语句生成器之前,您应该查看现有的库。您可能有一个中间 DSL(您的模板)被解析为 AST,然后处理该 AST 以生成 SqlCommand 或类似的东西。