在这种情况下,使用多态性而不是Enum有什么好处吗?

问题描述 投票:3回答:1

情景

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

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

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

要在where子句中替换的数据可以是整数,字符串,日期,并且每个数据都有不同的行为(例如:在字符串大小写中包含单个引号)。

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

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。所以我重构了使用基类

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

每个Type都有自己的实现:

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

问题

SOLID解决方案适用于我的测试,但在生产代码中,Database中有一个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)是否有另一种方法将SOLID OCP原则保留在数据库和业务代码中而不使用switch if if-else子句?

c# enums solid-principles open-closed-principle
1个回答
1
投票

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

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

但是,如果您希望通过设计进行扩展,并且在运行时无法执行此操作,则需要引入一种允许在运行时发现/注册新类型的方法。

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

EG

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

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

© www.soinside.com 2019 - 2024. All rights reserved.