对于以下情况,什么是好的设计模式?

时间:2014-10-27 13:03:04

标签: c# design-patterns

我手头有不同的字符串距离度量实现(所有这些都在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);
  }
  .
  . 
  .

但这对我来说并不是一个好的解决方案。我发现自己陷入了如此基本的设计问题,我感到很惊讶。任何帮助将不胜感激。

2 个答案:

答案 0 :(得分: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;
    }
}

如果您正在获取用户输入或配置设置以指定参数值,并且每次比较字符串时它们都会有所不同,那么工厂方法可能是一种合适的解决方案,这是最明显的方法'在你的答案中提出。

答案 1 :(得分:1)

如果你想要在方法签名上没有区别并希望隐藏实现细节,唯一的选择就是将所有内容都视为相同,即拥有一个签名并将其参数化为一体。

您可以考虑使用类或使用包含所有字段的方法向方法提供度量标准。然后,实现决定哪些参数有用,并将这些参数用于计算。