Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Command pattern - why encapsulate in an object?

Command pattern is for encapsulating commands in objects. But why not use function pointers instead? Why do I need to subclass Command for each operation? Instead I can have different functions and call the function pointers.

like image 892
Narek Avatar asked Apr 08 '14 11:04

Narek


People also ask

Which pattern is known to encapsulate a request as an object?

Definition: The command pattern encapsulates a request as an object, thereby letting us parameterize other objects with different requests, queue or log requests, and support undoable operations.

Is encapsulation used in design patterns?

Design Pattern based on Encapsulation in JavaMany design pattern in Java uses the encapsulation concept, one of them is Factory pattern which is used to create objects.

What is the purpose of Command design pattern?

In object-oriented programming, the command pattern is a behavioral design pattern in which an object is used to encapsulate all information needed to perform an action or trigger an event at a later time. This information includes the method name, the object that owns the method and values for the method parameters.

Which design pattern is also known as action or transaction and is used to encapsulate a request as an object to support rollback logging or transaction functionality?

A Command Pattern says that "encapsulate a request under an object as a command and pass it to invoker object. Invoker object looks for the appropriate object which can handle this command and pass the command to the corresponding object and that object executes the command". It is also known as Action or Transaction.


2 Answers

But why not use function pointers instead.

Because function pointers can't store arbitrary state. You'll often want the command to be parametrised when you create it. For example:

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

If you were to use a plain function pointer, then you'd need a different function for everything you might want to print.

Why I need to subclass Command class for each operation?

Because that's how old-school OOP works; although as mentioned above, you can use the fact that it's an object to parametrise it rather than subclass it.

Luckily, modern C++ has better facilities:

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
like image 162
Mike Seymour Avatar answered Sep 28 '22 08:09

Mike Seymour


Command pattern is much more than just executing a function. It encapsulates data and logic inside a class and provides an object that could easily be passed as a parameter. Besides executing tasks, it could also fire events, parse and clean up data and much more, and that's where inheritance and template methods come handy, which you won't get using function pointers. Also, implementing undo and redo is very easy using commands.

like image 41
Mercurial Avatar answered Sep 28 '22 09:09

Mercurial