C#工厂模式

时间:2009-09-19 16:56:43

标签: c# design-patterns database-design factory-pattern

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

我根据Granville Barnett在DotNetSlackers.com

的文章为我的工厂创建了以下结构

factory pattern http://img11.imageshack.us/img11/8382/factoryi.jpg

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

有没有人有这样的模式的例子?请告诉我。 谢谢, -Robert

1 个答案:

答案 0 :(得分:4)

我认为这个提议的解决方案不仅仅是简单地将数据源与代码模板相关联,就像你现在所拥有的那样。实际上,我甚至会说通过推送模板架构和将信息呈现到数据库来减少灵活性,这将使您的应用程序更难维护。

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

Document { Author, DateModified }
Picture { Size, Caption, Image }
Song { Artist, Length, AlbumCover }

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

让我们看看你提出的设计下的渲染。您将查询数据库中的渲染,然后调整您正在发出的一些HTML,比如因为您想要一个绿色背景的文档和一个蓝色的图片。为了争论,让我们说你意识到你真的需要三种背景颜色的歌曲,两种用于图片,一种用于文档。现在,除了更改要应用渲染值的参数化模板之外,您还在查看数据库模式更改(已提升并推出)。

让我们进一步说你决定Document结果需要一个下拉控件,Picture需要几个按钮,而歌曲需要一个声音播放器控件。现在,每个数据源的每个模板都会发生巨大变化,所以你就可以回到起步的地方了,除非你现在有一个数据库层。

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

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

对以下评论的回应:

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

switch (resultType)
{
    case (ResultType.Song):
      factory = new SongResultFactory();
      template = factory.BuildResult();
      break;
    // ...

您有输出给定模板的逻辑。如果你想要一个比long switch语句更紧凑的东西,你可以在字典中创建映射,如下所示:

IDictionary<ResultType, ResultFactory> TemplateMap;
mapping = new Dictionary<ResultType, ResultFactory>();
mapping.Add(ResultType.Song, new SongResultFactory());
// ... for all mappings.

然后,您可以执行以下操作来代替switch语句:

template = TemplateMap[resultType].CreateTemplate();

我的主要论点是,在某些时候你仍然需要维护映射 - 无论是在数据库中,是一个大的switch语句,还是需要初始化的这个IDictionary实例。

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

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

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