Command design pattern¶
Command is another design pattern that can be simplified by using functions that are passed as arguments:
The aim of the command design pattern is to decouple an object that calls an
operation from the Receiver object that implements the operation. In the
example from the design pattern book, each Caller
object is a menu item in a graphical application, and the Receiver
objects are the document to be edited or the application itself. For this
purpose, a Command object is placed between the two, which implements an
interface with a single method that calls a method in the Receiver to
perform the desired operation. In this way, the Caller object does not
need to know the interface of the Receiver, and different Receivers can
be customised using different Command subclasses. Caller is
configured with a ConcreteCommand command and calls its
execute() method to execute it.
Commands are an object-orientated replacement for callbacks. [1]
The question now is whether we really need such an object-oriented replacement
for callbacks in Python? Can’t we just give the Caller a function
instead? So instead of calling Command.execute(), the caller could simply
call command(). Command can be a class that implements
__call__() and instances of Command would be callables, each
containing a list of functions for future calls, for example:
1class MacroCommand:
2 """A command that executes a list of command."""
3
4 def __init__(self, commands):
5 self.commands = list(commands)
6
7 def __call__(self):
8 for command in self.commands:
9 command()
- Lines 4–5
creates a list from the command arguments and ensures that it is iterable.
- Line 7–8
creates a local copy of the command references in each
MacroCommandinstance. When an instance ofMacroCommandis called, each command inself.commandsis called in turn.