命令模式 - 为什么封装在对象中?

Nar*_*rek 8 oop encapsulation design-patterns command-pattern

命令模式用于封装对象中的命令.但为什么不使用函数指针呢?为什么我需要为每个操作子类化Command?相反,我可以有不同的函数并调用函数指针.

Mik*_*our 12

但为什么不使用函数指针.

因为函数指针不能存储任意状态.您经常希望在创建命令时对其进行参数化.例如:

struct command {
    virtual ~command() {}
    virtual void do_it() = 0;
};

struct say_something : command {
    // store a message to print later
    say_something(std::string message) : message(message) {}

    // print the stored message
    void do_it() override {std::cout << message << '\n';}

    std::string message;
};

std::unique_ptr<command> say_hello(new say_something("Hello!"));

// later

say_hello->do_it();  // prints stored string
Run Code Online (Sandbox Code Playgroud)

如果您使用普通函数指针,那么您可能需要一个不同的函数来处理您想要打印的所有内容.

为什么我需要为每个操作子类化Command类?

因为这就是老式OOP的工作原理; 虽然如上所述,您可以使用这样一个事实:它是一个参数化的对象而不是它的子类.

幸运的是,现代C++有更好的设施:

typedef std::function<void()> command;

// print a static string
command say_hello = []{std::cout << "Hello!\n";};

// store a string to print later
std::string goodbye = "Goodbye!";
command say_goodbye = [goodbye]{std::cout << goodbye << '\n';};

// later

say_hello();    // prints static string
say_goodbye();  // prints string stored in the command
Run Code Online (Sandbox Code Playgroud)

  • @Narek但只有在您创建命令时,Command模式才允许您在调用命令时提供参数.因此,您需要一个对象来存储它们,以便它们在被调用时可用. (4认同)

Mer*_*ial 6

命令模式不仅仅是执行一个函数.它将数据和逻辑封装在类中,并提供可以轻松作为参数传递的对象.除了执行任务之外,它还可以触发事件,解析和清理数据等等,这就是继承和模板方法派上用场的地方,你不会使用函数指针.此外,使用命令实现撤消和重做非常容易.