如何重构这个巨大的switch语句?

3
我继承了一些代码,其中有一个500行的switch语句。基本上,它会根据string任务进行切换并执行相应的操作。
我已经将每个case语句移动到一个新类中的自己的方法中。巨大的switch语句仍然存在,但是每种情况只是调用一个方法而不是内联逻辑,所以它更加整洁。
问题在于这些方法修改了很多不同的东西。50%的方法不需要传入任何参数。约40%需要5个参数,其余10%需要每个10个参数。
目前这样做是可以的,但我想让它变得更好。要么摆脱switch语句,要么以某种方式降低传入参数的数量。
我想使用一个将string映射到ActionDictionary来消除整个switch,但这行不通,因为我正在使用许多ref参数(原始类型),并且没有办法将它们传递给构造函数并稍后进行引用修改。
那个问题的明显解决方案就是将所有16个左右的变量放入单独的类中并通过该类传递,但其中许多变量并不相关,因此它只是用一个问题替换了另一个问题(具有非凝聚数据类的长参数列表)。
想知道是否有其他改进此代码的方法。谢谢阅读。

1
你能否使用反射和接口来实现某些功能? - jcolebrand
5
如果没有关于switch语句的具体信息以及它与其他代码的关系,回答可能有些困难。这个switch语句中的条件和操作是否都相关,或者只是一种应该完全删除的“兜底”情况?请提供更多上下文信息。 - pvanhouten
2
反射并不那么慢,你知道的。 - jcolebrand
可能是大型Switch语句:糟糕的OOP?的重复。 - Luke Girvin
你应该提供一些方法调用的示例。 - Loïc Faure-Lacroix
显示剩余4条评论
3个回答

3

如果没有代码可供查看,我唯一能给出的建议就是你应该考虑使用SOLID设计原则,以测试为目的进行重构。 我会尝试为每个逻辑模块(或开关条件)创建不同的类,通过这些对象的构造函数传入依赖项(而不是作为方法参数),并尝试创建一些统一的接口,您可以使用这些接口来编写测试。 您可能需要通过引入工厂来提取这些对象的条件创建。听起来很混乱。祝好运。


3

由于您的问题没有包含代码,答案也无法提供。我认为最好的做法是指向一本有史以来最好的软件书籍之一的第82页: 重构: 改善既有代码的设计

"面向对象代码最明显的症状之一是相对较少的switch语句。大多数情况下,您看到switch语句时应该考虑使用多态性。"

然后他列出了一些特定的模式,以帮助实现这一点。


1

在委托中,您可以使用ref参数,但不能使用内置的ActionFunc泛型委托。您必须像这样定义自己的委托:

public delegate void DelegateWithRefParameters(ref int i, ref long l, ref bool b, ref object o);

public class Program
{
    public static void Main(string[] args)
    {
        int i = 0;
        long l = 0;
        bool b = false;
        object o = null;

        var lookup = new Dictionary<string, DelegateWithRefParameters>() 
        {
            { "object", ModifyObject },
            { "int", ModifyInt },
            { "bool", ModifyBool },
        };

        string s = "object";

        lookup[s](ref i, ref l, ref b, ref o);
    }

    private static void ModifyObject(ref int i, ref long l, ref bool b, ref object o)
    {
        o = new object();
    }

    private static void ModifyInt(ref int i, ref long l, ref bool b, ref object o)
    {
        i++;
    }

    private static void ModifyBool(ref int i, ref long l, ref bool b, ref object o)
    {
        b = !b;
    }              

}

您只需修改所有方法以使用相同的签名即可。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接