有没有一种很好的方法来使用多态来删除这个switch语句?

时间:2014-03-31 22:13:12

标签: refactoring polymorphism

我一直在阅读重构和用多态替换条件语句。我遇到的麻烦是,当你有一个更复杂的情况时,似乎只对我有意义,在没有多态的情况下,你必须多次重复相同的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来确定要实例化的类。它看起来像是没有任何好处会更加复杂。如果我要保留这些类并使用依赖于文件类型的更多内容,那么它将消除在多个位置执行相同的切换,但这是单用的。这是正确的,还是有一些我没有看到的理由或技术,这使得使用多态类层次结构做到这一点是个好主意?

2 个答案:

答案 0 :(得分:1)

如果你有一个抽象的ComponentImporter类,带有具体的子类FromA和FromB,你可以实例化其中一个,并将它放在Map中。然后你可以调用componentImporterMap.get(xmlFile.Name.LocalName).importComponents()并避免切换。

答案 1 :(得分:0)

与所有设计选择一样,背景是关键。在这种情况下,你有一个看起来很简单的类来处理两个非常相似的任务。如果两个Import方法包含非常少的重复代码,那么将它们包含在单个类中可能是最好的选择,因为正如您所说,它降低了复杂性。

但是,您将来可能会使用此类,甚至可以添加新类型的导入。在这种情况下,如果类是多态的,那么该类将更具可重用性。

此外,由于这些方法非常相似,因此您可能会有一堆重复的代码,您可以将它们保存在基类中,并且只将特定于导入的代码放在子类中。

另外,正如Carl所提到的,有许多方法可以在不使用案例陈述的情况下实现这种逻辑。