The command pattern is used to separate each request or command from the object on which those requests are performed. This allows a request to be parameterized for different scenarios and moves the code into different classes for the execution of requests.
By using the command pattern in our programs and applications, we are able to incorporate functionalities (such as queueing, request logging, and undo/redo operations) with a lot of ease. This is because each request is an independent entity from other classes and objects; therefore, we can modify or update a request without worrying about affecting other requests or objects.
– Separation of concerns: The remote will know how to make a request but is not concerned with what happens or how the request is executed.
– Programming to an Interface : Because each request is an implementation of the same interface, it allows new command objects to be created independently without altering any previously written code.
– Low coupling: The command objects only interact with other classes when a request is made for a particular action without sharing any other information. Due to this, changes in one class’s implementation won’t affect how the other class communicates with it.
Below is an example code of the command pattern. The Television
class is a simple object and the Remote
class acts as the caller, using the TelevisionOnCommand
and TelevisionOffCommand
classes to interact with the Television
objects.
The TelevisionOnCommand
and TelevisionOffCommand
classes are concrete implementations of the Command
interface.
// the television classexport class Television {state: boolean = false;on() {this.state = true;}off() {this.state = false;}}// the command interfaceinterface Command {execute(): any;undo(): any;}// the televisiononcommand is a concrete implementation of the command interfaceclass TelevisionOnCommand implements Command {television: Television;constructor(television: Television) {this.television = television;}execute() {this.television.on();}undo() {this.television.off();}}// the televisionoffcommand is a concrete implementation of the command interfaceclass TelevisionOffCommand implements Command {television: Television;constructor(television: Television) {this.television = television;}execute() {this.television.off();}undo() {this.television.on();}}// the remote in this case is the callerclass Remote {onCommand: Command;offCommand: Command;setCommand(onCommand, offCommand) {this.onCommand = onCommand;this.offCommand = offCommand;}onButtonClick() {this.onCommand.execute();}offButtonClick() {this.offCommand.execute()}}let television = new Television();let televisionOnCommand = new TelevisionOnCommand(television);let televisionOffCommand = new TelevisionOffCommand(television);let remote = new Remote();remote.setCommand(televisionOnCommand, televisionOffCommand);console.log('state of television before remote is used:', television.state);remote.onButtonClick();console.log('state of television after remote is used:', television.state);