C#工厂模式

C#工厂模式,c#,design-patterns,database-design,factory-pattern,C#,Design Patterns,Database Design,Factory Pattern,我正在构建一个搜索应用程序,该应用程序对多个不同的数据源进行了索引。当对搜索引擎索引执行查询时,每个搜索结果都指定它来自哪个数据源。我已经建立了一个工厂模式,用于为每种类型的搜索结果显示不同的模板,但我已经意识到,随着越来越多的数据源被搜索引擎索引,这种模式将变得更加难以管理(即,必须为每个新数据源创建新的代码模板) 我根据Granville Barnett在 为了使这个搜索应用程序更易于维护,我的想法是创建一组数据库表,用于定义我的factory模式可以引用的单个模板类型,以确定要构造的模板

我正在构建一个搜索应用程序,该应用程序对多个不同的数据源进行了索引。当对搜索引擎索引执行查询时,每个搜索结果都指定它来自哪个数据源。我已经建立了一个工厂模式,用于为每种类型的搜索结果显示不同的模板,但我已经意识到,随着越来越多的数据源被搜索引擎索引,这种模式将变得更加难以管理(即,必须为每个新数据源创建新的代码模板)

我根据Granville Barnett在

为了使这个搜索应用程序更易于维护,我的想法是创建一组数据库表,用于定义我的factory模式可以引用的单个模板类型,以确定要构造的模板。我想我需要一个查找表,用于指定基于搜索结果数据源构建的模板类型。然后,我需要一个表来指定要为该模板类型显示哪些字段。我还需要一个表(或模板表中的其他列),用于定义如何呈现该字段(即超链接、标签、CssClass等)

有人有这样的模式的例子吗?请让我知道。 谢谢
-Robert

我想说的是,这个建议的解决方案的可维护性不亚于将数据源与代码模板相关联,正如您现在所做的那样。事实上,我甚至会说,如果将模板模式推送到数据库并将信息呈现到数据库中,您将失去灵活性,这将使您的应用程序更难维护

例如,假设您有这些具有属性的数据源(如果我理解正确):

然后,您的搜索结果中可能会有其中一个数据源。每个元素的渲染方式都不同(图片可以使用锚定在左侧的预览图像进行渲染,或者歌曲可以显示相册封面等)

让我们看一下您建议的设计下的渲染。您将查询数据库中的渲染,然后调整正在发出的一些HTML,例如,因为您希望文档背景为绿色,图片背景为蓝色。为了便于讨论,假设您意识到歌曲需要三种背景色,图片需要两种背景色,文档需要一种背景色。现在,您将看到一个数据库模式更改,除了更改要应用渲染值的参数化模板之外,还将升级并推出该更改

让我们进一步假设,您决定文档结果需要一个下拉控件,图片需要几个按钮,歌曲需要一个声音播放器控件。现在,每个数据源的每个模板都发生了巨大的变化,所以您回到了开始的位置,只是现在您有了一个数据库层

这就是设计中断的原因,因为您现在已经失去了为每个数据源定义不同模板的灵活性。另一个损失是在源代码管理中对模板进行版本控制

我将介绍如何在发出的视图中重用公共元素/控件,但在工厂中保持模板和数据源之间的映射,并将模板作为每个数据源的单独文件。查看如何通过CSS或类似配置设置维护渲染。为了便于维护,请考虑将映射导出为简单的XML文件。要部署一个新的数据源,只需添加一个映射,创建适当的模板和CSS文件,然后将它们放到预期的位置

对以下评论的答复:

我的意思是一个简单的switch语句就足够了:

switch (resultType)
{
    case (ResultType.Song):
      factory = new SongResultFactory();
      template = factory.BuildResult();
      break;
    // ...
其中,您具有输出给定模板的逻辑。如果需要比长switch语句更紧凑的语句,可以在字典中创建映射,如下所示:

IDictionary<ResultType, ResultFactory> TemplateMap;
mapping = new Dictionary<ResultType, ResultFactory>();
mapping.Add(ResultType.Song, new SongResultFactory());
// ... for all mappings.
我的主要论点是,在某个时候,您仍然需要维护映射——要么在数据库中,要么在一个大的switch语句中,要么在这个需要初始化的IDictionary实例中

您可以进一步将映射存储在一个简单的XML文件中,该文件可以读入:

<TemplateMap>
    <Mapping ResultType="Song" ResultFactoryType="SongResultFactory" />
    <!-- ... -->
</TemplateMap>


并使用reflection等填充IDictionary。您仍在维护映射,但现在是XML文件,这可能更易于部署。

再次感谢您的解释。能有另一双眼睛和另一种观点总是好的!你的想法给了我更多的想法去考虑。再次感谢罗伯特
template = TemplateMap[resultType].CreateTemplate();
<TemplateMap>
    <Mapping ResultType="Song" ResultFactoryType="SongResultFactory" />
    <!-- ... -->
</TemplateMap>