我一直在阅读重构和用多态替换条件语句。我遇到的麻烦是,当你有一个更复杂的情况时,似乎只对我有意义,在没有多态的情况下,你必须多次重复相同的switch语句或if-elses。我不知道如果你只做一次就有意义 - 你必须在某个地方有条件,对吗?
作为一个例子,我最近写了下面的类,它负责读取XML文件并将其数据转换为程序的对象。我们支持的文件有两种可能的格式,所以我只是在类中编写了一个方法来处理每个文件,并使用case-switch来确定使用哪一种:
public class ComponentXmlReader
{
public IEnumerable<UserComponent> ImportComponentsFromXml(string path)
{
var xmlFile = XElement.Load(path);
switch (xmlFile.Name.LocalName)
{
case "CaseDefinition":
return ImportComponentsFromA(xmlFile);
case "Root":
return ImportComponentsFromB(xmlFile);
}
}
private IEnumerable<UserComponent> ImportComponentsFromA(XContainer file)
{
//do stuff
}
private IEnumerable<UserComponent> ImportComponentsFromB(XContainer file)
{
//do stuff
}
}
据我所知,我可以为此编写一个类层次结构来进行解析,但我没有看到这里的优势 - 我仍然需要使用一个case-switch来确定要实例化的类。它看起来像是没有任何好处会更加复杂。如果我要保留这些类并使用依赖于文件类型的更多内容,那么它将消除在多个位置执行相同的切换,但这是单用的。这是正确的,还是有一些我没有看到的理由或技术,这使得使用多态类层次结构做到这一点是个好主意?
答案 0 :(得分:1)
如果你有一个抽象的ComponentImporter类,带有具体的子类FromA和FromB,你可以实例化其中一个,并将它放在Map中。然后你可以调用componentImporterMap.get(xmlFile.Name.LocalName).importComponents()并避免切换。
答案 1 :(得分:0)
与所有设计选择一样,背景是关键。在这种情况下,你有一个看起来很简单的类来处理两个非常相似的任务。如果两个Import方法包含非常少的重复代码,那么将它们包含在单个类中可能是最好的选择,因为正如您所说,它降低了复杂性。
但是,您将来可能会使用此类,甚至可以添加新类型的导入。在这种情况下,如果类是多态的,那么该类将更具可重用性。
此外,由于这些方法非常相似,因此您可能会有一堆重复的代码,您可以将它们保存在基类中,并且只将特定于导入的代码放在子类中。
另外,正如Carl所提到的,有许多方法可以在不使用案例陈述的情况下实现这种逻辑。