我继承了一个代码库,它大量使用switch语句(C#,FWIW)来驱动某些逻辑。它是一个多租户网络应用程序,其中一组切换语句与内容的显示方式有关,另一组与功能链接有关,至少在大多数情况下是这样。
我有机会重构,因此我正在使用与内容相关的switch语句并计划使用Render()方法创建基本Content类,然后为需要覆盖基本实现的类型设置特定子类。
但是在极少数情况下,呈现HTML基于内容类型和特定租户,我不希望所有新的Render()方法都与我开始时完全相同的问题。是否有一种模式可以帮助解决这种情况?
我在SO上看到了一些其他类似的问题,但我不确定如何在这里应用答案。
答案 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)开关即可。如有必要,您可以向超类添加新方法,并将新内容类型的租户特定处理添加到子类。
添加新租户也很容易。只是将它们分类。
可以使用开关,但是如果你重复它们,那就错了。
答案 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();
}
...
}
这种设计当然取决于干净地抽象内容类型差异的能力。