我手头有不同的字符串距离度量实现(所有这些都在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);
}
.
.
.
但这对我来说并不是一个好的解决方案。我发现自己陷入了如此基本的设计问题,我感到很惊讶。任何帮助将不胜感激。
答案 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)
如果你想要在方法签名上没有区别并希望隐藏实现细节,唯一的选择就是将所有内容都视为相同,即拥有一个签名并将其参数化为一体。
您可以考虑使用类或使用包含所有字段的方法向方法提供度量标准。然后,实现决定哪些参数有用,并将这些参数用于计算。