1

我正在编写一个从给定文件中解析文本的类。有几种不同的文本“类型”,每种的解析规则都不同。

例如,一种类型的文本,我们将称之为“纯文本”,是一个简单的字符串,解析器会为其去除额外的空格。因此,例如,如果我有 "The quick brown fox\r\njumped over the lazy brown dogs\r\n",解析器只会返回"The quick brown fox jumped over the lazy brown dogs"(换行符转换为单个空格)。

其他文本代表具有给定分隔符的表,因此它可能看起来像"First Name,Last Name,DOB",并且解析器的工作是返回一个包含每个逗号分隔值的数组。

(实际实现比这更复杂,但这是一个很好的简化)。

最初我打算通过创建一个名为类似TextType、 值PlainText和的枚举来解决这个问题TableText。然后我可以有一个看起来像的方法

public string ParseText(string textToParse, TextType textType)

我很快意识到这不起作用,因为当 textType 是 PlainText 时,返回值应该是 a string,但是当 textType 是 TableText 时,返回值应该是 a string[]

一种选择是始终返回一个字符串 [] 并且将其作为一个给定的,即 PlainText 将始终返回一个大小为 1 的数组。不过我对此并不感到太兴奋,因为它在语义上似乎不正确并且可能是令人困惑。

另一种选择是为每个 TextType 编写一个方法,这样我就可以

public string ParsePlainText(string textToParse)

public string[] ParseTableText(string textToParse)

我不喜欢这种方法的原因是它消除了原始方法与枚举提供的一些灵活性。例如,预计我稍后会添加其他文本类型;将来我可能会有一种客户希望识别为 HeadingText 的文本类型,但会以与纯文本相同的方式进行解析。使用原始方法,包含解析方法的类的公共接口不必更改,因为我只需向TextType枚举并修改 ParseText 方法的内部结构。此外,我认为当只有一个方法可以调用时,它只是一个更简洁的界面,客户端只需传递 TextType(他知道),其他一切都为他处理(而不是必须从类似命名的列表中选择)每次添加新文本类型时都会增长的方法)。

最后,我可以只返回一个既可以继承string又可以string[]继承的对象(因为这是 C#,我可以直接 return object),并让客户端转换为适当的类型。我认为这是最糟糕的方法,因为它要求客户端知道应该“实际”返回什么,并且通过更改从 Parse 类返回的类型并且直到运行时才遇到结果错误,有很大的潜力让某人打破每个依赖项(因为基本上没有类型检查开始)。

对于这种情况,是否有“正确”或最佳的方法?

4

3 回答 3

2

有几种方法..但首先想到的是使用interfaces

interface ITextParser {
    string Parse(string text);
}

public class TableTextParser : ITextParser {
    public string Parse(string text) {
        // specific table parsing stuff here
    }
}

public class PlainTextParser : ITextParser {
    public string Parse(string text) {
        // specific plain text parsing stuff here
    }
}

然后,您的主要功能可能会变成某种工厂,如下所示:

public ITextParser CreateParserFor(string textToParse) {
    // logic here to determine the sort of parser you require:
    if (typeOfTextIsTable)
        return new TableTextParser();

    if (typeOfTextIsPlain)
        return new PlainTextParser();
}

然后你也许可以这样称呼它:

var parser = CreateParserFor(string_here);
var result = parser.Parse(string_here);
于 2013-01-29T01:10:00.257 回答
1

让我们试着澄清一下这个问题。您有两种类型的文本(至少目前,可能会增长到更多类型),即:

  1. 具有相同的输入类型,String。
  2. 有不同的输出类型,字符串和数组。
  3. 有不同的实现。

未来添加的类型可能需要不同类型的输出/返回。现在的问题是,尝试将这些功能组合成一种方法真的合乎逻辑吗?我看到您的目标是为客户端提供统一/通用接口,但是,如果返回类型不同,我不确定您是否可以提供这样的接口。

我不认为在接口中有许多类似的方法是一件坏事。有很多知名的库都是这样的。

在我看来,你的第二种方法,有类似

public string ParsePlainText(string textToParse)
public string[] ParseTableText(string textToParse)

尽管您怀疑,但它比其他建议的方式更清洁。特别是,如果您从客户端视图中查看它(与返回大小为 1 的数组或使用强制转换等的情况相比)。

于 2013-01-29T03:03:11.420 回答
0

对于建议的任何方法,您可以从表示结果集合ParseResults的方法中返回一个对象。Parse然后,这可以公开一个iterator以迭代ParseResults.

这使您的签名保持统一,IMO 不会混淆。

希望这可以帮助。

于 2013-01-30T00:38:21.080 回答