有一些令人讨厌的遗留代码.
std::string xxx = GetCommand(); // get "CommandX"; if (xxx == "Command1") { return new Command1(); } else if (xxx == "Command2") { return new Command2(); } ... else if (xxx == "Command100") { return new Command100(); }
我想改进这个代码结构.
有太多的比较.所以我把它们放到地图上.
for (int i = 0; i < GetCommandCount(); ++i) { // key is a command string // value is a function pointer which creates it's instance map.insert(command,a function pointer); } // then ICommand* pCommand = map.getInstance(command);
但是,如果新的命令来了,这种方式必须每次增加一些功能.
是的,这些功能可能是合理的.但是所有的功能只是返回新的CommandNNN();我想有办法删除重复.
你怎么想?
解决方法
由于所有函数都返回新的CommandNNN();可以使用模板函数:
template <class T> CommandBase* createCommand() { return new T(); }
并绑定到您的地图中的此功能:
map.insert(std::make_pair("Command1",&createCommand<Command1>)); map.insert(std::make_pair("Command2",&createCommand<Command2>)); map.insert(std::make_pair("Command3",&createCommand<Command3>));
这样可以避免为每个命令创建一个新功能.但是,map.insert-statements中仍然会有一些重复.这可以通过使用宏进一步减少,如果这是你的一杯茶:
#define INSERT(cmd) map.insert(std::make_pair(#cmd,&createCommand<cmd>)); INSERT(Command1); INSERT(Command2); INSERT(Command3); #undef INSERT
要么
#define INSERT(n) map.insert(std::make_pair("Command" #n,&createCommand<Command ## n>)); INSERT(1); INSERT(2); INSERT(3); #undef INSERT
我怀疑你甚至可以让预处理器为你做一些计数,但这不在我的域之外.
应用更多的宏,以及一些全球国家,这两个都被许多人所皱眉,你可以获得更加紧密的耦合:
#include <map> #include <string> #include <cassert> class CommandBase {}; static std::map<std::string,CommandBase* (*)()> g_commandMap; template <class C> CommandBase* createCommand() { return new C(); } class CommandRegistrer { public: CommandRegistrer(const std::string& name,CommandBase* (*instantiator)()) { g_commandMap.insert(std::make_pair(name,instantiator)); } }; #define COMMAND_CLASS(n) \ class Command##n; \ CommandRegistrer g_commandRegistrer##n("Command" #n,createCommand<Command##n>); \ class Command##n : public CommandBase COMMAND_CLASS(1) { /* implementation here */ }; COMMAND_CLASS(2) { /* implementation here */ }; int main() { assert(g_commandMap.find("Command1") != g_commandMap.end()); }