Command

The command pattern is a method of encapsulating both the parameters to a method, as well as the current object state, and which method is to be called. In effect the command pattern packs up everything needed to call a method at a later date into a nice little package. Using this approach one can issue a command and wait until a later date to decide which piece of code will execute the command. This package can then be queued or even serialized for later execution. Having a single point of command execution also allows for easily adding functionality such as undo or command logging.

This pattern can be a bit difficult to imagine so let's break it down into its components:

Command

Command message

The first component of the command pattern is, predictably, the command itself. As I mentioned, the command encapsulates everything needed to invoke a method. This includes the method name, the parameters, and any global state. As you can imagine keeping track of global state in each command is very difficult. What happens if the global state changes after the command has been created? This dilemma is yet another reason why using a global state is problematic and should be avoided.

There are a couple of options for setting up commands. At the simple end of the scale all that is needed is to track a function and a set of parameters. Because functions are first class objects in JavaScript, they can easily be saved into an object. We can also save the parameters to the function into a simple array. Let's build a command using this very simple approach.

The deferred nature of commands suggests an obvious metaphor in the land of Westeros. There are no methods of communicating quickly in Westeros. The best method is to attach small messages to birds and release them. The birds have a tendency to want to return to their homes, so each lord raises a number of birds in their home and, when they come of age, sends them to other lords who might wish to communicate with them. The lords keep an aviary of birds and retain records of which bird will travel to which other lord. The king of Westeros sends many of his commands to his loyal lords through this method.

The commands sent by the king contain all necessary instructions for the lords. The command may be something like bring your troops and the arguments to that command may be a number of troops, a location, and a date by which the command must be carried out.

In JavaScript the simplest way of representing this is through an array:

var simpleCommand = new Array();
simpleCommand.push(new LordInstructions().BringTroops);
simpleCommand.push("King's Landing");
simpleCommand.push(500);
simpleCommand.push(new Date());

This array can be passed around and invoked at will. To invoke it, a generic function can be used:

simpleCommand[0](simpleCommand[1], simpleCommand[2], simpleCommand[3]);

As you can see, this function only works for commands with three arguments. You can, of course, expand this to any number:

simpleCommand[0](simpleCommand[1], simpleCommand[2], simpleCommand[3], simpleCommand[4], simpleCommand[5], simpleCommand[6]);

The additional parameters are undefined, but the function doesn't use them so there are no ill effects. Of course, this is not at all an elegant solution.

It is desirable to build a class for each sort of command. This allows you to ensure the correct arguments have been supplied and easily distinguish the different sorts of commands in a collection. Typically, commands are named using the imperative, as they are instructions. Examples of this are BringTroops, Surrender, SendSupplies, and so on.

Let's transform our ugly simple command into a proper class:

class BringTroopsCommand {
  constructor(location, numberOfTroops, when) {
    this._location = location;
    this._numberOfTroops = numberOfTroops;
    this._when = when;
  }
  Execute() {
    var receiver = new LordInstructions();
    receiver.BringTroops(this._location, this._numberOfTroops, this._when);
  }
}

We may wish to implement some logic to ensure that the parameters passed into the constructor are correct. This will ensure that the command fails on creation instead of on execution. It is easier to debug the issue during creation rather than during execution as execution could be delayed, even for days. The validation won't be perfect, but even if it catches only a small portion of the errors it is helpful.

As mentioned these commands can be saved for later use in memory or even written to disk.

Invoker

The invoker is the part of the command pattern which instructs the command to execute its instructions. The invoker can really be anything: a timed event, a user interaction, or just the next step in the process may all trigger invocation. When we executed the simpleCommand command in the preceding section, we were playing at being the invoker. In a more rigorous command the invoker might look something like the following:

command.Execute()

As you can see, invoking a command is very easy. Commands may be invoked at once or at some later date. One popular approach is to defer the execution of the command to the end of the event loop. This can be done in a node with:

process.nextTick(function(){command.Execute();});

The function process.nextTick defers the execution of a command to the end of the event loop such that, if it is executed next time the process has nothing to do.

Receiver

The final component in the command pattern is the receiver. This is the target of the command execution. In our example we created a receiver called LordInstructions:

class LordInstructions {
  BringTroops(location, numberOfTroops, when) {
    console.log(`You have been instructed to bring ${numberOfTroops} troops to ${location} by ${when}`);
  }
}

The receiver knows how to perform the action that the command has deferred. There need not be anything special about the receiver, in fact it may be any class at all.

Together these components make up the command pattern. A client will generate a command, pass it off to an invoker that may delay the command or execute it at once, and the command will act upon a receiver.

In the case of building an undo stack, the commands are special, in that they have both an Execute and an Undo method. One takes the application state forward and the other takes it backwards. To perform an undo, simply pop the command off the undo stack, execute the Undo function, and push it onto a redo stack. For redo, pop from redo, execute Execute, and push to the undo stack. Simple as that, although one must make sure all state mutations are performed through commands.

The GoF book outlines a slightly more complicated set of players for the command pattern. This is largely due to the reliance on interfaces that we've avoided in JavaScript. The pattern becomes much simpler thanks to the prototype inheritance model in JavaScript.

The command pattern is a very useful one for deferring the execution of some piece of code. We'll actually explore the command pattern and some useful companion patterns in Chapter 10, Messaging Patterns.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset