2017-01-16 63 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

相關問題