重构两个级别的切换语句

时间:2009-11-10 22:39:56

标签: c# design-patterns

我继承了一个代码库,它大量使用switch语句(C#,FWIW)来驱动某些逻辑。它是一个多租户网络应用程序,其中一组切换语句与内容的显示方式有关,另一组与功能链接有关,至少在大多数情况下是这样。

我有机会重构,因此我正在使用与内容相关的switch语句并计划使用Render()方法创建基本Content类,然后为需要覆盖基本实现的类型设置特定子类。

但是在极少数情况下,呈现HTML基于内容类型和特定租户,我不希望所有新的Render()方法都与我开始时完全相同的问题。是否有一种模式可以帮助解决这种情况?

我在SO上看到了一些其他类似的问题,但我不确定如何在这里应用答案。

3 个答案:

答案 0 :(得分:1)

抱歉,我的OOP设计技巧有点生疏。你可以感谢Lisp宏;]

也许使用两个工厂类会有效吗?

Content()类构造函数接受变量$ content_type和$ feature。然后构造函数返回一个Content()子类的实例,该子类包含一个属性,该属性初始化为Feature()工厂类生成的Feature()子类的实例,使用$ feature的值来选择适当的子类。当调用Content()子类render()方法时,此render()方法可以包括对Feature()工厂中的方法的调用,该方法可以补充或进一步处理render()方法生成的数据。如果不需要通过Feature()方法进行进一步处理,您可以简单地省略这些调用。

答案 1 :(得分:1)

我想我能帮到你。我要做的是:

创建1个类来处理渲染控制流:

class Renderer
{
    Tenant _tenant;

    void Render(ContentType type)
    {
        switch (type)
        {
            case ContentType.JSON: 
                _tenant.RenderJSON();
                break;
            default:
                _tenant.RenderHTML();
                break;
        }
    }
}

然后为租户创建1个超类:

class Tenant
{
    virtual void RenderJSON() { ... };
    virtual void RenderHTML() { ... };
}

最后,为租户特定的东西创建子类:

class JoeBlow : Tenant
{
    override void RenderJSON() { // joe blow's json };
}

这应该给你一个很好的模型:

  • 每个租户1个班级(这很好,因为你说每个租户的行为会发生变化)
  • 1个超级类别,用于放置普通行为(适用于所有租户)
  • 将contentType解析为render方法的1个位置。

添加新内容类型很简单:只需更新(1)开关即可。如有必要,您可以向超类添加新方法,并将新内容类型的租户特定处理添加到子类。

添加新租户也很容易。只是将它们分类。

可以使用开关,但是如果你重复它们,那就错了。

答案 2 :(得分:0)

如果可能的话,您可以根据内容类型抽象出现罕见的差异,然后为每个租户创建一组渲染器,每个内容类型都有辅助对象。这将问题转化为n + m问题而不是n * m。其中n和m分别是用户数和内容类型。然后你可以像这样构造渲染器:

// uses a DefaultContentTypeDelegate
IRenderer tenantADefault = new TenantARenderer();
// specify a specific content type helper object
IRenderer tenantAType1 = new TenantARender(new ContentType1Delegate());

然后,每个租户的渲染器的渲染方法都可以实现Template Method Pattern,偶尔会在contentTypeDelegate上调用一些方法。

class TenantARenderer : IRenderer {
    ...
    public render() {
        // do a bunch of tenant A specific stuff
        this.contentTypeDelegate.doSomeContentTypeSpecificStuff();
        // do some more tenant A stuff
        this.contentTypeDelegate.doSomeOtherContentTypeSpecificStuff();
    }
    ...
}

这种设计当然取决于干净地抽象内容类型差异的能力。