C# 工厂模式

发布于 2024-08-05 19:57:11 字数 735 浏览 2 评论 0原文

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

我根据 Granville Barnett 的文章为我的工厂创建了以下结构 DotNetSlackers.com

工厂模式 http://img11.imageshack.us /img11/8382/factoryi.jpg

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

有人有这样的模式的例子吗?请告诉我。 谢谢, ——罗伯特

I am building a search application that has indexed several different data sources. When a query is performed against the search engine index, each search result specifies which data source it came from. I have built a factory pattern that I used to display a different template for each type of search result, but I've realized that this pattern will become more difficult to manage as more and more data sources are indexed by the search engine (i.e new code template has to be created for each new data source).

I created the following structure for my factory based off of an article by Granville Barnett over at DotNetSlackers.com

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

In order to make this search application easier to maintain, my thought was to create a set of database tables that can be used to define individual template types that my factory pattern could reference in order to determine which template to construct. I figured that I'd need to have a look up table that would be used to specify the type of template to build based off of the search result data source. I'd then need to have a table(s) to specify which fields to display for that template type. I'd also need a table (or additional columns within the template table) that would be use to define how to render that field (i.e. Hyperlink, Label, CssClass, etc).

Does anyone have any examples of a pattern like this? Please let me know.
Thanks,
-Robert

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

酷炫老祖宗 2024-08-12 19:57:11

我认为这个建议的解决方案的可维护性并不比简单地将数据源与代码模板相关联(就像您现在所拥有的那样)一样。事实上,我什至会说,通过推送模板架构并将信息呈现到数据库,您将失去灵活性,这将使您的应用程序更难以维护。

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

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 文件中,这可能更容易部署。

I would offer that this proposed solution is no less maintainable than simply associating a data source to the code template, as you currently have now. In fact, I would even go so far as to say you're going to lose flexibility by pushing the template schema and rendering information to a database, which will make your application harder to maintain.

For example, let's suppose you have these data sources with attributes (if I'm understanding this correctly):

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

You then may have one of each of these data sources in your search results. Each element is rendered differently (Picture may be rendered with a preview image anchored to the left, or Song could display the album cover, etc.)

Let's just look at the rendering under your proposed design. You're going to query the database for the renderings and then adjust some HTML you are emitting, say because you want a green background for Documents and a blue one for Pictures. For the sake of argument, let's say you realize that you really need three background colors for Songs, two for Pictures, and one for Documents. Now, you're looking at a database schema change, which is promoted and pushed out, in addition to changing the parameterized template you're applying the rendering values to.

Let's say further you decide that the Document result needs a drop-down control, the Picture needs a few buttons, and Songs need a sound player control. Now, each template per data source changes drastically, so you're right back where you started, except now you have a database layer thrown in.

This is how the design breaks, because you've now lost the flexibility to define different templates per data source. The other thing you lose is having your templates versioned in source control.

I would look at how you can re-use common elements/controls in your emitted views, but keep the mapping in the factory between the template and the data source, and keep the templates as separate files per data source. Look at maintaining the rendering via CSS or similar configuration settings. For making it easier to maintain, considering exporting the mappings out as a simple XML file. To deploy a new data source, you simply add a mapping, create the appropriate template and CSS file, and drop them in to expected locations.

Response to comments below:

I meant a simple switch statement should suffice:

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

Where you have the logic to output a given template. If you want something more compact than a long switch statement, you can create the mappings in a dictionary, like this:

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

Then, instead of a switch statement, you can do this one-liner:

template = TemplateMap[resultType].CreateTemplate();

My main argument was that at some point you still have to maintain the mappings - either in the database, a big switch statement, or this IDictionary instance that needs to be initialized.

You can take it further and store the mappings in a simple XML file that's read in:

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

And use reflection et. al. to populate the IDictionary. You're still maintaining the mappings, but now in an XML file, which might be easier to deploy.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文