17

我有一个解析一些模板文件的代码,当它找到一个占位符时,它用一个值替换它。就像是:

<html>
<head>
    <title>%title%</title>
</head>
<body bgcolor="%color%">
...etc.

在代码中,解析器找到那些,调用这个函数:

string getContent(const string& name)
{
    if (name == "title")
        return page->getTitle();
    else if (name == "color")
        return getBodyColor();
    ...etc.
}

然后用返回值替换原来的占位符。

在实际情况下,它不是一个虚拟网页,并且可能出现许多 (50+) 个不同的占位符。

我的代码是 C++,但我猜任何语言都存在这个问题。我猜这更多是关于算法和面向对象设计的。唯一重要的是必须编译它,即使我想要我不能有任何动态/评估代码。

我虽然关于实施责任链模式,但它似乎不会改善这种情况。

更新:我也担心另一个线程中的这个评论。我应该关心它吗?

4

6 回答 6

26

使用将标签名称映射到标签处理程序的字典。

于 2009-03-18T18:41:46.250 回答
5

你想用 polymorphism 替换条件。大致:

string getContent(const string& name) {
    myType obj = factory.getObjForName(name);
    obj.doStuff();
}

doStuff 重载的地方。

于 2009-03-18T18:43:55.543 回答
3

你考虑过 XSLT 吗?它非常适合这种事情。我开发了一个内容管理系统,它做了完全相同的事情,并发现 XSLT 非常有效。解析器为您做了很多工作。

更新:Steven 的评论提出了一个重要的观点——如果你决定走 XSLT 路线,你会希望你的模板是有效的 XHTML。另外-我会为您的替换令牌使用不同的分隔符。不太可能自然发生的事情。我用了#!PLACEHOLDER#!在我的 CMS 中。

于 2009-03-18T18:44:31.687 回答
3

i'll combine 3 ideas:

  1. (from Steven Hugig): use a factory method that gets you a different class for each selector.
    • (from Neil Butterworth): inside the factory, use a dictionary so you get rid of the big switch(){}.
    • (mine): add a setup() method to each handler class, that adds itself (or a new class instance) to the dictionary.

explaining a bit:

  • make an abstract class that has a static dict, and methods to register an instance with a selector string.
  • on each subclass the setup() method registers itself with the superclass' dict
  • the factory method is little more than a dictionary read
于 2009-03-18T19:01:27.043 回答
2

Rather than parsing, have tried just reading the template into a string and then just performing replaces.

fileContents = fileContents.Replace("%title%", page->getTitle());
fileContents = fileContents.Replace("%color%", getBodyColor());
于 2009-03-18T18:44:45.133 回答
2

As "Uncle" Bob Martin mentioned in a previous podacast with Joel and Jeff, pretty much anything you come up with is going to essentially be reproducing the big switch statement.

If you feel better implementing one of the solutions selected above, that's fine. It may make your code prettier, but under the covers, it's essentially equivalent.

The important thing is to ensure that there is only one instance of your big switch statement. Your switch statement or dictionary should determine which class handles this tag, and then subsequent determinations should be handled using polymorphism.

于 2009-03-18T19:31:17.533 回答