我有一个程序应该从控制台读取命令,并根据命令执行多个操作之一。以下是我到目前为止的情况:
void ConwayView::listening_commands() {
string command;
do {
cin >> command;
if ("tick" == command)
{
// to do
}
else if ("start" == command)
{
// to do for start
}
...
} while (EXIT != command);
}
如果有大量命令,使用switch
代替if
语句会有所帮助。您建议使用哪些模式来提供交互式命令行?
答案 0 :(得分:4)
如果命令数很少且可能的参数很少,你可以继续使用switch case!
如果命令数量增加,请考虑the command design pattern(恕我直言,某些strategy pattern伪装:cf Using a strategy pattern and a command pattern了解命令和策略模式之间的差异。)
如果您的大部分命令都是共享相同行为的一部分,请不要忘记the template method pattern。
如果创建命令对象的复杂性增加(即解码/理解命令行输入的复杂性),您应该开始查看the interpreter design pattern
如果在借助解释器模式进行设计时,您碰巧看到了一些复杂性(如果解释器需要太多工作,您会看到语法问题等等),那么您应该查看DSL, domain specific language,并设计适合(并且仅适合)您自己输入的语言。
答案 1 :(得分:3)
有多种方法可以解决这个问题,“正确”解决方案的含义是值得商榷的。如果我要为自己的工作解决它,我会创建一个自定义结构的表。类似的东西:
struct CommandStruct {
char *command;
int (*commandHandler)(/*params*/);
} commandTable[] = {
{ "tick", tickCommand },
{ "start", startCommand },
...
};
然后我的处理循环将遍历此表的每个元素,寻找正确的匹配,例如:
for (int i = 0; i < TABLE_SIZE; ++i) {
if (command == commandTable[i].command) { /* using whatever proper comparison is, of course */
commandTable[i].commandHandler(/*params*/);
break;
}
}
答案 2 :(得分:2)
不是真正的模式,但通常是一种好方法:
#include <map>
#include <functional>
#include <string>
#include <iostream>
typedef std::map< std::string, std::function<void(void)> > command_dict;
// ^^^^^^^^
// the signature of your commands. probably should have an error code.
void command1() { std::cout << "commanda" << std::endl; }
void command2() { std::cout << "commandb" << std::endl; }
void command3() { std::cout << "commandc" << std::endl; }
int main() {
command_dict c;
c["a"] = &command1;
c["b"] = &command2;
c["c"] = &command3;
std::string input;
while(std::getline(std::cin, input)) { // quit the program with ctrl-d
auto it = c.find(input);
if(it != end(c)) {
(it->second)(); // execute the command
} else {
std::cout << "command \"" << input << "\" not known" << std::endl;
}
}
}
答案 3 :(得分:0)
使用新的和改进的方法随意执行一堆命令: int happy_time = 5; int a = happy_time; int muddy_dirt = 1; int b = muddy_dirt; int c = happy_time * muddy_dirt //非常混乱的东西
这可能是最简单的方法....
答案 4 :(得分:-1)
if
- else
阶梯很好。
原则上它可以用map<string, Function>
代替,但是对于这个具体情况你不会得到任何东西(即使有大量命令,也增加了没有特别增益的复杂性)。
当我最初写这篇文章时,我忘了提及:
如果你不这样做,那么if
- else
阶梯会变得非常混乱...... map
解决方案需要单独的功能,因此可能看起来比一切 - 直接在这里if
- else
阶梯。但它确实是单独的功能,然后提供一定程度的清晰度,而map
减少一点(在维护地图时增加额外的工作,以及额外的间接处理水平)。
另一方面,由于“从控制台读取命令”表示交互式输入,并且图片中有用户,您不希望从同一行读取两个或多个命令输入。因为那会搞砸提示,对用户来说似乎很困惑。因此,不要使用>>
一次读取输入的“单词”,而是使用std::getline
一次读取整行输入。
答案 5 :(得分:-2)
如果命令很大,则必须使用类似数据库的访问。