C# 工厂模式

5
我正在构建一个搜索应用程序,它已经索引了几个不同的数据源。当针对搜索引擎索引执行查询时,每个搜索结果都指定了它来自哪个数据源。我已经构建了一个工厂模式,用于显示每种类型的搜索结果的不同模板,但我意识到随着搜索引擎索引越来越多的数据源(即为每个新数据源创建新代码模板),这种模式将变得更加难以管理。
我基于Granville Barnett在DotNetSlackers.com上的一篇文章创建了以下结构,用于我的工厂: 工厂模式 http://img11.imageshack.us/img11/8382/factoryi.jpg 为了使这个搜索应用程序更易于维护,我的想法是创建一组数据库表,可以用来定义单个模板类型,我的工厂模式可以引用这些表来确定要构建哪个模板。我认为需要一个查找表,用于根据搜索结果数据源指定要构建的模板类型。然后,我需要一个或多个表来指定该模板类型显示哪些字段。我还需要一个表(或模板表中的其他列)来定义如何呈现该字段(即超链接、标签、CssClass等)。
有人有这样的模式示例吗?请告诉我。 谢谢, -Robert
1个回答

4
我认为这个提议的解决方案和你目前所使用的将数据源与代码模板关联的方式一样易于维护。实际上,我甚至认为,将模板架构和渲染信息推送到数据库中会使您失去灵活性,从而使应用程序更难以维护。
例如,假设您有以下具有属性的数据源(如果我理解得正确):
Document { Author, DateModified }
Picture { Size, Caption, Image }
Song { Artist, Length, AlbumCover }

您的搜索结果可能包含这些数据源中的每一个。每个元素都会以不同的方式呈现(例如,图片可能会显示左侧锚定的预览图像,而歌曲则可能显示专辑封面等)。
让我们来看看您提出的设计下的渲染。您将查询数据库以获取渲染,并调整一些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 语句:

template = TemplateMap[resultType].CreateTemplate();

我的主要观点是,在某个时候,您仍然需要维护映射 - 可以在数据库、一个大的switch语句中或需要初始化的IDictionary实例中完成。

您可以进一步将映射存储在简单的XML文件中,然后进行读取:

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

使用反射等技术来填充IDictionary。您仍然在维护映射,但现在是在XML文件中,这可能更容易部署。


谢谢您再次的解释。得到另一个人的眼睛和意见总是很好的!您的想法给了我更多要考虑的点子。再次感谢。- 罗伯特 - Robert Williams

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接