用什么替换巨型 switch 语句?

发布于 2024-07-14 20:18:14 字数 821 浏览 5 评论 0原文

我有一个代码可以解析一些模板文件,当它找到占位符时,它会用一个值替换它。 类似于:

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

我考虑过实施责任链模式,但似乎并没有多大改善情况。

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

I have a code that parses some template files and when it finds a placeholder, it replaces it with a value. Something like:

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

In code, the parser finds those, calls this function:

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

and then replaces the original placeholder with returned value.

In real case, it is not a dummy web page, and there are many (50+) different placeholders that can occur.

My code is C++, but I guess this problem exists with any language. It's more about algorithms and OO design I guess. Only important thing is that this must be compiled, even if I wanted I couldn't have any dynamic/eval'd code.

I though about implementing Chain of Responsibility pattern, but it doesn't seem it would improve the situation much.

UPDATE: and I'm also concerned about this comment in another thread. Should I care about it?

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

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

发布评论

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

评论(6

故事灯 2024-07-21 20:18:14

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

Use a dictionary that maps tag names to a tag handler.

森林很绿却致人迷途 2024-07-21 20:18:14

您希望用多态性替换条件。 粗略地说:

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

doStuff 超载的地方。

You want replace conditional with polymorphism. Roughly:

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

where doStuff is overloaded.

独自←快乐 2024-07-21 20:18:14

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

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

Have you considered XSLT? It's very well suited to this kind of thing. I developed a content management system that did the exact same thing and found XSLT to be very effective. The parser does a lot of the work for you.

UPDATE: Steven's comment raises an important point- you'll want your templates to be valid XHTML if you decide to go the XSLT route.
Also- I would use a different delimiter for your replacement tokens. Something less likely to occur naturally. I used #!PLACEHOLDER#! in my CMS.

空城仅有旧梦在 2024-07-21 20:18:14

我将结合 3 个想法:(

  1. 来自 Steven Hugig):使用工厂方法为每个选择器提供不同的类。
    • (来自 Neil Butterworth):在工厂内部,使用字典,这样就可以摆脱大的 switch(){}
    • (我的):向每个处理程序类添加一个 setup() 方法,该方法将其自身(或新的类实例)添加到字典中。

解释一下:

  • 创建一个具有静态字典的抽象类,以及使用选择器字符串注册实例的方法。
  • 在每个子类上,setup() 方法将自身注册到超类的字典中,
  • 工厂方法只不过是读取的字典

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
梦醒灬来后我 2024-07-21 20:18:14

尝试将模板读入字符串,然后执行替换,而不是解析。

fileContents = fileContents.Replace("%title%", page->getTitle());
fileContents = fileContents.Replace("%color%", getBodyColor());

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());
べ繥欢鉨o。 2024-07-21 20:18:14

正如“叔叔”鲍勃·马丁在之前与乔尔和杰夫一起的播客中提到的,几乎你想出的任何东西本质上都会复制大的 switch 语句。

如果您觉得实施上面选择的解决方案之一效果更好,那也没有问题。 它可能会使您的代码更漂亮,但在幕后,它本质上是等效的。

重要的是确保大 switch 语句只有一个实例。 您的 switch 语句或字典应确定哪个类处理此标记,然后应使用多态性来处理后续确定。

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.

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