C++摆脱了Singletons:替代了仿函数和静态方法

Kaa*_*Kaa 4 c++ singleton structure functor

我的崇高任务是摆脱单身人士和静态阶级.

背景:
我有以下结构:

  • Cmd
    经常实例化对象,它拥有命令(string)的名称,以及任何类的静态方法作为指针的仿函数.
    它通常在诸如Input,Console,Render等主类中创建,并且引用类中创建它的方法,为这些方法提供运行时语言接口.
    Cmds还以字符串数组的形式解释参数,其中第一个参数是Cmd的名称,所有连续字符串是被调用的静态方法的直接参数.参数count和argument数组存储在Commander中,并在每次Cmd调用之前更改.
  • Commander
    Commander用于解释字符串命令(可以直接或通过控制台),它执行Cmd,它作为字符串存储在缓冲区中(通过调用它的仿函数).

问题:
问题是我试图摆脱所有的静态类(我现在变成了用于测试的单例),并且我使系统完全模块化并且松散耦合.这反过来阻止我进行Cmds可能指向的静态调用.

第一直觉是将函数从typedef更改为模板类,这将存储一个对象和方法,但它看起来非常混乱和复杂,我个人不舒服:

Cmd::create("toggleconsole", Console::toggle);
Run Code Online (Sandbox Code Playgroud)

至:

Cmd::create("toggleconsole", new FunctorObject<Console>(&Console::get(), &Console::toggle));
Run Code Online (Sandbox Code Playgroud)

最终的Cmd创建看起来非常模糊和误导谁负责Functor解除分配.

我也正在将Cmd创建从静态方法调用移动到Commander类中,所以它看起来像commander.createCmd("command_name",...); 而不是Cmd :: create("command_name",...); 这是因为Commander不再是静态的(或单例),因此它处理的所有命令都必须属于它.

但是,我完全不知道我的选项/替代方案是注册Cmds,并通过允许向Commander发出字符串命令来维持松散耦合.

我已经考虑过让每个主类派生自一个CmdListener类,它会在创建时用Commander注册该对象,然后在执行期间将命令传递给覆盖"onCmd(const Cmd&command)"的所有已注册对象.

这也留下了一些未解答的问题:Cmd将如何调用应该调用哪个类的方法?保持指针是没有意义的,并且会受到高度默默无闻的影响(如上所示).另外,我希望不为每个可以处理该cmd的类重新解释onCmd方法中的字符串.

这是很多信息,但有没有人对如何处理这个问题有任何想法?

此外,我的所有类都必须知道Commander和Console对象,它们不再是单例/静态.到目前为止,我已将它们放在Context对象中,并将它像一个小胶囊一样传递.关于如何解决这些后单例残留问题的任何想法?

这个项目是我个人的工作,我打算在我的简历上使用它 - 因此,我不希望我的潜在雇主看到任何单身人士(我也不想解释为什么,因为我可以证明他们自己并非真正必要).

万分感谢!

编辑:排版.

Pup*_*ppy 5

这是function班上的工作.你可以在Boost中找到一个,或者在TR1或C++ 0x中找到一个.例如std::function<void()>,它看起来像.这通常与bind您合作,如果您想以通用方式引用功能对象,而不是按值获取它们,您将需要它,并且也可以在Boost,TR1或C++ 0x中找到它们.如果你有lambda函数,你也可以使用它们,这是一种很好的方法.

class Commander {
    std::map<std::string, std::function<void()>> commands;
public:
    void RegisterCommand(std::string name, std::function<void()> cmd) {
        commands[name] = cmd;
    }
    void CallCommand(std::string name) {
        commands[name]();
    }
};
void sampleFunc() {
    std::cout << "sampleFunc()" << std::endl;
}
struct sampleStruct {
    int i;
    void operator()() {
        std::cout << i;
        std::cout << "sampleStruct()() and the value of i is " << i << std::endl;
    }
};

int main() {
    Commander c;
    c.RegisterCommand("sampleFunc", sampleFunc);
    sampleStruct instance;
    instance.i = 5;
    c.RegisterCommand("sampleStruct", instance);
    std::string command;
    while(std::cin >> command && command != "exit") {
        c.CallCommand(command);
    }
    std::cin.get();
}
Run Code Online (Sandbox Code Playgroud)