2017-01-16 77 views
3

场景在这种情况下使用Enum多态性有什么好处吗?

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

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

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); 
} 

每种类型都有其自己的实现:

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

问题

固溶工作了我的测试,但在生产代码数据库中有一个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的方法?因为如果创建一个新的类型,则必须实现一个新的else子句
2)是否有另一种方法将SOLID OCP原则保留在数据库和业务代码中,而不使用开关或if-else子句?

+0

如果您正在构建SQL语句,为什么不使用库和准备好的语句来为您处理这些事情? – Seth

+0

查询是通过现有的用户界面创建的,因此它必须支持在模板中定义的占位符。它也必须支持级联查询这就是为什么我决定构建自己的组件。 –

回答

1

Replacing contionnal with polymorphysim将确保决策只会发生一次,所以它可能是一个好主意。如果您在某个时间点对每种类型进行了额外的专门操作,那么它们应该很容易实现。

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

但是,如果您希望通过设计进行扩展,并且在运行时不会这样做,您需要引入一种方法,以便在运行时发现/注册新类型。

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

E.g.

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

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

+0

这是一个很好的解决方案。我认为从中吸取的教训是:有时可以不使用SOLID,但保持良好的模式。我会更多地搜索你提到的那些库。 –

+0

@DaniloRuziska SOLID原则是指南,但你必须保持务实。如果一个静态工厂完成了工作,那么最好坚持使用它,而不是建立一个非常复杂的可扩展机制,以便在不需要时自动发现新的过滤器类型。 – plalx

+0

@plalx奥卡姆的剃刀是'违反'原则的良好借口。 – CSharpie

相关问题