The Command Pattern is a data-driven design pattern, which belongs to the category of behavioral patterns. It is also known as the Action Pattern or the Transaction Pattern. The Command Pattern wraps a request in the form of a command within an object and passes it to the invoking object. The invoking object then looks for a suitable object that can handle the command and passes the command to the appropriate object. The object then queues the request or logs the request and supports undo operations.
In software design, we often need to send requests to some objects without knowing who the receiver of the request is, or what operation is being requested. We only need to specify the specific request receiver at runtime. In such cases, the Command Pattern can be used to eliminate the coupling between the sender and receiver of the request, making the calling relationship between objects more flexible. The Command Pattern fully decouples the sender and receiver, removing direct reference relationships between them. The object sending the request only needs to know how to send the request, without needing to know how to fulfill the request. The Command Pattern can also be used to implement transaction-based systems. Once a command is executed, the history of the command is retained. If the command is successfully executed, everything is fine; otherwise, the history can be traversed, and the executed commands can be undone.
Using the Command Pattern may lead to an excessive number of concrete command classes in some systems. This is because a specific command class needs to be designed for each command. Thus, some systems may require a large number of concrete command classes, which can affect the use of the Command Pattern.
// Assume we have a light bulb and we want to control it using a remote controlclassBulb{turnOn(){ console.log("Bulb has been lit!");}turnOff(){ console.log("Darkness!");}}classCommand{execute(){thrownewError("Abstract method cannot be called");}redo(){thrownewError("Abstract method cannot be called");}undo(){thrownewError("Abstract method cannot be called");}}classTurnOnCommandextendsCommand{constructor(bulb){super();this.bulb = bulb;}execute(){this.bulb.turnOn();}undo(){this.bulb.turnOff();}redo(){this.execute();}}classTurnOffCommandextendsCommand{constructor(bulb){super();this.bulb = bulb;}execute(){this.bulb.turnOff();}undo(){this.bulb.turnOn();}redo(){this.execute();}}classRemoteControl{submit(command){ command.execute();}}(function(){var bulb =newBulb();var turnOn =newTurnOnCommand(bulb);var turnOff =newTurnOffCommand(bulb);var remote =newRemoteControl(); remote.submit(turnOn);// Bulb has been lit! remote.submit(turnOff);// Darkness!})();