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

时间:2014-04-08 11:08:23

标签: oop design-patterns encapsulation command-pattern

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

2 个答案:

答案 0 :(得分: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

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

  

为什么我需要为每个操作创建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

答案 1 :(得分:6)

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