2014-10-27 77 views
4

我有不同的字符串距離度量實現手頭(所有這些都在C#中),例如,Levensthein,NeedlemanWunsch,Jaccard等。這些工作基本相同;以兩個字符串作爲輸入並返回範圍[0,1]中的相似度分數。所以,我打算讓這些類來實現相同的基本界面,如下所示:什麼是以下情況的良好設計模式?

public interface IStringDistanceMetric 
{ 
    //Return a similarity between 0 and 1. 
    double CompareSimilarity(string strA, string strB); 
} 

我的每一個指標都將實現此方法。但是有些指標可以直接對兩個字符串進行操作,沒有任何其他輸入,並且有一些指標需要一些額外的參數(例如對輸入字符串之一的間隙進行懲罰等)。一般來說,我可以在構造函數階段或計算相似性分數之前給這些參數。

我的問題是,一般來說,爲了處理具體距離類之間的這種差異,一個好的設計實踐是什麼?我的目標是,在決定使用特定類型的度量標準之後,希望使用任何距離度量標準的客戶端代碼應該忽略任何基礎實現細節。最明顯的辦法是實施類似:

IStringDistanceMetric metric; 
    if(metricType == Metric.NeedlemanWunsch) 
    { 
    metric = new NeedlemanWunsch(parametersNW); 
    } 
    else if(metricType == Metric.Levensthein) 
    { 
    metric = new Levensthein(parametersL); 
    } 
    . 
    . 
    . 

但是這對我來說不是一個好的解決方案。我有點驚訝地發現自己陷入了這樣一個基本的外觀設計問題。任何幫助,將不勝感激。

+3

你知道你要預先使用哪個嗎?也許一個工廠會更適合在這裏。這樣客戶端只需要一個實例,工廠方法就包含這個「if else」的東西並返回接口。這使得工廠可以訪問參數的假設 - 它總是可以爲這些參數提供參數。還允許您保留您的策略模式,以便返回接口的實現,這很好。 – 2014-10-27 13:07:14

+0

你試圖做這件事的方式沒有錯,你有兩個獨立的alghorithms檢查這兩個字符串。讓他們在不同的功能和使用if來選擇你應該使用哪一個是正確的方式做到這一點。 – Vajura 2014-10-27 13:08:53

+0

同意@AdamHouldsworth。此外,我建議你的客戶端代碼將「stringDistanceMetric」_typed_作爲接口(而不是實際的類類型),因此可以注入不同的具體類型。 – heltonbiker 2014-10-27 13:11:14

回答

2

我想這很大程度上取決於它是如何使用的;這些參數的值是固定的還是應該在進行比較時提供?如果可能值的這些參數的數量是非常低的,在.NET用於StringComparers的設計可以遵循(的sourceof.net提供):

private static readonly StringComparer _invariantCulture = new CultureAwareComparer(CultureInfo.InvariantCulture, false);   
private static readonly StringComparer _invariantCultureIgnoreCase = new CultureAwareComparer(CultureInfo.InvariantCulture, true);  
private static readonly StringComparer _ordinal = new OrdinalComparer(false); 
private static readonly StringComparer _ordinalIgnoreCase = new OrdinalComparer(true);   

public static StringComparer InvariantCulture { 
    get { 
     return _invariantCulture; 
    } 
} 

如果您收到用戶輸入或配置設置來指定參數值,而且每次比較字符串時它們都會有所不同,工廠方法可能是一個合適的解決方案,在您的答案中提供了「最明顯的方式」。

+0

+1我沒有想到這個解決方案,它確實是一個很好的解決方案。這確實存在一個問題,即調用者必須知道實現細節,這是我認爲OP想要避免的。但那只是我的兩分錢。 – 2014-10-27 13:22:47

+0

我認爲可能需要經常更改參數。所以,一般來說,我應該有一個類:'StringMetricFactory',它接受所有相關參數,並生成我想要使用的度量類的具體實例,並將其作爲對'IStringDistanceMetric'接口的引用返回。這是一個合適的解決方案? – 2014-10-27 13:24:41

+0

我這麼認爲,或者創建一個方法,返回所需的數據,並使用'Func GetMeThisMetrics'在'計算器'中'注入'。 – 2014-10-27 13:26:36

1

如果您希望在方法簽名中沒有任何區別,並希望隱藏實現細節,唯一的選擇是將所有內容都對待,即擁有一個簽名並對其進行參數化,以便適合所有人。

您可以考慮使用一個類或使用包含所有字段的方法將度量提供給方法。然後實現決定哪些參數是有用的,並將這些參數用於計算。

相關問題