我有一个解析一些模板文件的代码,当它找到一个占位符时,它会用一个值替换它。类似的东西:
<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 ++,但我猜这个问题存在于任何语言中。我猜它更多的是关于算法和OO设计。唯一重要的是必须编译它,即使我希望我没有任何动态/评估代码。
我虽然关于实施责任链模式,但似乎不会改善这种情况。
更新:我也关注另一个帖子中的this comment。我应该关心它吗?
答案 0 :(得分:25)
使用将标记名称映射到标记处理程序的字典。
答案 1 :(得分:4)
你想要replace conditional with polymorphism。大致是:
string getContent(const string& name) {
myType obj = factory.getObjForName(name);
obj.doStuff();
}
doStuff重载的地方。
答案 2 :(得分:3)
你考虑过XSLT吗?它非常适合这种事情。我开发了一个完全相同的内容管理系统,发现XSLT非常有效。解析器为您完成了很多工作。
更新:史蒂文的评论提出了一个重点 - 如果你决定采用XSLT路线,你会希望你的模板是有效的XHTML。 另外 - 我会使用不同的分隔符来替换令牌。不太可能自然发生的事情。我用#!PLACEHOLDER#!在我的CMS中。
答案 3 :(得分:3)
我将结合3个想法:
switch(){}
。setup()
方法,将自身(或新的类实例)添加到字典中。解释一下:
static
dict的抽象类,以及使用选择器字符串注册实例的方法。setup()
方法使用超类'dict 答案 4 :(得分:2)
不是解析,而是尝试将模板读入字符串然后只执行替换。
fileContents = fileContents.Replace("%title%", page->getTitle());
fileContents = fileContents.Replace("%color%", getBodyColor());
答案 5 :(得分:2)
作为"Uncle" Bob Martin mentioned in a previous podacast with Joel and Jeff,您提出的几乎任何内容都将基本上复制大转换语句。
如果您觉得更好地实施上面选择的解决方案之一,那很好。它可能会使您的代码更漂亮,但在封面下,它基本上是等效的。
重要的是确保只有一个big switch语句实例。你的switch语句或字典应该确定哪个类处理这个标记,然后应该使用多态来处理后续的确定。