有很多方法可以解决这个问题,具体取决于您究竟需要什么。 OO 世界中流行的一种方法是所谓的Command Pattern(类似的方法存在于其他编程范例中,它们只是名称不同,或者被认为非常明显,甚至根本没有特定的名称)。
基本思路是这样的:你想执行某个命令,但是你想执行命令的时间和你决定执行什么命令的时间是不同的。所以解决这个问题的方法是简单地创建一个包含执行命令所需信息的对象,将该对象传递到决定何时执行的地方,然后该代码可以随心所欲地运行命令。
这是 C++ 中的样机(注意:实际上并未编译此代码,可能包含小错误 - 只是为了传达这个想法)。
#include <memory>
#include <vector>
/// this is an abstract class that gives us an interface to use
class DrawCommand {
public:
virtual void Draw() = 0;
};
/// one kind of thing you might want to draw
class DrawTree : public DrawCommand {
public:
void Draw() override {
// tree drawing code
}
};
/// another kind of thing you might want to draw
class DrawCat : public DrawCommand {
public:
void Draw() override {
// cat drawing code
}
};
/// we can even come up with ways to combine these in interesting ways
class DrawABunchOfThings : public DrawCommand {
std::vector<std::unique_ptr<DrawCommand>> things;
public:
DrawABunchOfThings(std::vector<std::unique_ptr<DrawCommand>> things)
: things{std::move(things)}
{}
void Draw() override {
for(auto &thing : things) {
thing->Draw();
}
}
};
/// this is where we decide what we will draw
std::unique_ptr<DrawCommand> PrepareDraw() {
if(someCondition) {
// just a cat
return std::make_unique<DrawCat>();
} else if(someOtherCondition) {
// just a tree
return std::make_unique<DrawTree>();
} else {
// forest with a cat hidden inside
return std::make_unique<DrawABunchOfThings>(
std::vector<std::unique_ptr<DrawCommand>>{
std::make_unique<DrawTree>(),
std::make_unique<DrawTree>(),
std::make_unique<DrawCat>()
std::make_unique<DrawTree>(),
}
);
}
}
/// this is where we will do the actual drawing
/// note that any arbitrary amount of code can go between
/// PrepareDraw and ExecuteDraw
void ExecuteDraw(DrawCommand &command) {
// this can of course have a bunch of elaborate
// code here as well -- also, DrawCommand::Draw might
// take extra parameters here, like 2D or 3D transforms,
// time since we last drew something, or whatever
command.Draw();
}
注意,如果你只需要一个方法,C++ 已经有 std::function 的形式,所以你可以说 using DrawCommand = std::function<void()>; 并完成它,这也将立即允许你使用它使用 lambda:
int nTimes = 10;
DrawCommand drawNTimesCommand = [nTimes]() {
for(int i = 0; i < nTimes; ++i) {
// draw something
}
};
// --- any code you like here ---
// actually execute the draw command
drawNTimesCommand();