在C#中的大开关重构的建议 [英] Refactoring advice for big switches in C#

查看:176
本文介绍了在C#中的大开关重构的建议的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在C#/的WinForms,可以让一个网格用户放置物品,为游戏创造水平的应用程序。它有用于放置瓷砖/灯/门/实体等。目前我只用一个枚举存储当前选择的工具,并有一个switch语句运行每个工具代码的工具。正如我一直在增加更多的工具来应用它开始变得像意大利面条,有很多重复的代码。

I have an application in C#/Winforms that lets users place objects on a grid to create levels for a game. It has several tools for placing tiles/lights/doors/entities etc. Currently I just use an enum for storing the currently selected tool and have a switch statement to run each tools code. As I've been adding more tools to the application it's starting to get spaghetti like, with lots of duplicated code.

下面是鼠标按下功能的缩减版本,我的编辑器类:

Here is a cutdown version of the mouse down function in my editor class:

    public void OnEditorViewMouseDown(Point mousePos)
    {
        // Check if the click is out of bounds.
        if (IsLocationOOB(mousePos)) return;

        if (CurrentTool == ToolType.GroundTile)
        {
            // Allow drags along whole tiles only.
            m_DragManager.DragType = DragManager.DragTypeEnum.Tile;
            m_DragManager.StartDrag(mousePos);
        }
        else if (CurrentTool == ToolType.WallTile)
        {
            // Allow drags along grid edges only.
            m_DragManager.DragType = DragManager.DragTypeEnum.Edge;
            m_DragManager.StartDrag(mousePos);
        }
        else if (CurrentTool == ToolType.PostTile)
        {
            // Allow drags along grid points only.
            m_DragManager.DragType = DragManager.DragTypeEnum.Point;
            m_DragManager.StartDrag(mousePos);
        }
        else if (CurrentTool == ToolType.AreaLight)
        {
            // Allow drags anywhere. ie. not snapped to the grid in some way.
            m_DragManager.DragType = DragManager.DragTypeEnum.FreeForm;
            m_DragManager.StartDrag(mousePos);
        }
        else if (CurrentTool == ToolType.PointLight)
        {
            m_CurrentWorld.AddLight(TranslateToWorldCoords(mousePos));
        }
        else if (CurrentTool == ToolType.PlaceEntity)
        {
            m_CurrentWorld.PlaceEntity(TranslateToWorldCoords(mousePos));
        }
    }



此开关是在其他几项功能使用(的OnMouseMove, OnMouseUp),它似乎是不好的设计(大型交换机在多种功能复制)。有什么建议给一个更清洁,更可扩展的方式重构这样的事情?目前,我正在想有一个基地工具类,并让每个工具的它自己的类中的覆盖使用(onmousedown事件()等)的功能。这听起来合理的?

The switch is used in several other functions (OnMouseMove, OnMouseUp) and it seems like bad design (big switch copied in several functions). Any advice for refactoring something like this in a cleaner and more extensible way? I'm currently thinking of having a base Tool class and having each tool it's own class that overrides the functions it uses (OnMouseDown() etc.). Does this sound sensible?

感谢您的阅读。

推荐答案

您有良好的直觉。

通常,OOP,当你有如果的还是堆积如山交换机,它是一个强大的代码味道行。使这种气味消失的最好办法就是去与多态。

Usually, in OOP, when you have rows of if's or humongous switches, it's a strong code smell. The best way to make this smell go away is to go with polymorphism.

您应该继续与你的想法,有一个抽象基类BaseTool,用不同的OnXXX方法作为NOP(只返回,所以你只需要指定的行为,如果您的工具知道如何对方法的行为),并有每个工具从BaseTool继承和通过重写相关方法实现自己的行为。实施

You should go ahead with your idea, having a base abstract class BaseTool, with the different OnXXX methods implemented as nops (just returns, so you only have to specify the behavior if your tool knows how to act on the method), and have each tool inherit from BaseTool and implement its own behavior by overriding the relevant methods.

所以你的方法最终被

public void OnEditorViewMouseDown(Point mousePos)
{
  currentTool.OnEditorViewMouseDown(mousePos);
}



根据你的设计,你也应该考虑通过则DragManager的方法,以免被捆绑到实例变量周围铺设。配备了一切方法需要,无需取出一个EditorContext(含则DragManager)全局变量会使得你的方法更独立的,不易碎重构的时候。设计本身将取决于人的职责:谁是负责什么

Depending on your design, you should also consider passing the DragManager to the method, so as not to be tied to instance variables laying around. An EditorContext (containing the DragManager) fitted with everything the method needs without having to fetch "global" variables would make your method more self-contained and less brittle when refactoring. The design itself will depend on the responsability: who is in charge of what.

这篇关于在C#中的大开关重构的建议的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆