我正在编写一个解析给定文件中的文本的类。文本有一些不同的“类型”,解析规则各有不同。
例如,一种类型的文本,我们将只调用“纯文本”,是一个简单的字符串,解析器会删除额外的空格。例如,如果我有"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时,返回值应该是string
,但是当textType是TableText时,返回值应该是string[]
。
一个选项是始终返回一个字符串[]并且只是将它作为一个给定,PlainText将始终返回一个大小为1的数组。虽然因为它似乎在语义上看起来不正确并且可能令人困惑。
另一个选择是为每个TextType编写一个方法,所以我可以
public string ParsePlainText(string textToParse)
和
public string[] ParseTableText(string textToParse)
我不喜欢这种方法的原因是因为它消除了原始方法使用枚举提供的一些灵活性。例如,我预计稍后会添加其他文本类型;在将来,我可能会有一种客户希望识别为HeadingText的文本,但将以与纯文本相同的方式进行解析。使用原始方法,包含解析方法的类的公共接口不必更改,因为我可以向TextType
枚举添加新值并修改ParseText方法的内部。另外,我认为只有一种方法可以调用,它只是一个更清晰的界面,客户端只需要传递TextType(他知道)并为他处理其他所有事情(而不是从类似命名的列表中选择)每次添加新文本类型时增长的方法。)
最后,我可以返回string
和string[]
都继承的对象(因为这是C#,我可以返回object
),并让客户端转换为适当的类型。我认为这是所有方法中最糟糕的方法,因为它要求客户端知道应该“实际”返回什么,并且通过更改从Parse类返回的类型并且直到运行时才遇到结果错误,有很大的可能性来破坏每个依赖项(因为基本上没有类型检查开始)。
这种情况是否有“正确”或最佳方法?
答案 0 :(得分: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);
答案 1 :(得分:1)
让我们试着澄清一下这个问题。你有两种类型的文本(至少现在,可能会增长到更多类型),即:
未来添加的类型可能需要不同类型的输出/返回。现在的问题是,尝试将这些功能组合到一个方法中是否合乎逻辑?我看到你的目标是为客户端提供统一/通用的接口,但是,如果返回类型不同,我不确定你是否可以提供这样的接口。
我不认为在界面中有很多类似的方法是件坏事。这种方式有许多着名的图书馆。
在我看来,你的第二种方法,有
之类的东西public string ParsePlainText(string textToParse)
public string[] ParseTableText(string textToParse)
尽管你有所怀疑,但是比其他建议的方式更清洁。特别是,如果从客户端视图中查看它(与返回大小为1的数组或使用的数组等情况相比)。
答案 2 :(得分:0)
对于建议的任何方法,您可以从表示结果集合的ParseResults
方法返回Parse
个对象。然后,这可以公开iterator
以遍历ParseResults
。
这使您的签名保持统一,IMO不会混淆。
希望这有帮助。