This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money. Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.

define

Encapsulating a request as an object separates the responsibility for making the request from the responsibility for executing it. In this way, the two can communicate with each other through command objects. In this way, command objects can be stored, transferred, invoked, added and managed conveniently.

In real life, there are many examples of command mode. For example, when watching TV, we only need to click the remote control to complete the channel change, which is the command mode, completely decouples the channel change request from the channel change processing. The TV remote control (command sender) controls the TV (command receiver) by pushing buttons (specific commands).

advantages

  1. Reduce the coupling degree of the system by introducing middleware (abstract interface).
  2. Good scalability, easy to add or delete commands. Adding and deleting commands in command mode does not affect other classes and meets the open/Close principle.
  3. Macro commands can be implemented. Command mode can be combined with composite mode to assemble multiple commands into a composite command, known as a macro command.
  4. Easy to implement Undo and Redo operations. The command mode can be combined with the memo mode to realize command undo and restore.
  5. You can add additional functionality to existing commands. For example, logging, combined with the decorator pattern is more flexible.

disadvantages

  1. A large number of concrete command classes can be generated. Because each specific operation requires the design of a specific command class, this adds complexity to the system.
  2. The result of the command pattern is actually the result of the recipient’s execution, but in order to architecture in the form of commands and decouple requests from implementation, the introduction of additional type structures (requester and abstract command interface) makes it more difficult to understand. However, this is a common problem with design patterns. Abstraction inevitably increases the number of classes, and code abstraction is more difficult to understand than code aggregation.

The structure and implementation of command pattern

Related operations in the system can be abstracted into commands that separate the caller from the implementer. The structure is as follows. \

Pattern structure

The command mode contains the following primary roles.

  1. Abstract Command role: Declares the interface to execute commands and has the abstract method execute() to execute commands.
  2. Concrete Command role: A Concrete implementation class of an abstract Command class, which owns the receiver object and performs the operations to be performed by the Command by invoking the receiver’s functions.
  3. Implementer/Receiver: Performs operations related to command functions and is the real implementer of specific command object services.
  4. Invoker (Invoker) role: is the sender of the request, it usually has a number of command objects, and accesses the command object to perform the request, it does not directly access the receiver.

Its structure is shown in Figure 1.

Implementation of patterns

The code for command mode is as follows:

 package command;

public class CommandPattern {
    public static void main(String[] args) {
        Command cmd = new ConcreteCommand();
        Invoker ir = new Invoker(cmd);
        System.out.println("The customer accesses the caller's call() method..."); ir.call(); }}/ / the caller
class Invoker {
    private Command command;

    public Invoker(Command command) {
        this.command = command;
    }

    public void setCommand(Command command) {
        this.command = command;
    }

    public void call(a) {
        System.out.println("Caller executes command..."); command.execute(); }}// Abstract the command
interface Command {
    public abstract void execute(a);
}

// Specify the command
class ConcreteCommand implements Command {
    private Receiver receiver;

    ConcreteCommand() {
        receiver = new Receiver();
    }

    public void execute(a) { receiver.action(); }}/ / the recipient
class Receiver {
    public void action(a) {
        System.out.println("The receiver's action() method is called..."); }}Copy the code

The running results of the program are as follows:

The customer accesses the caller's call() method... The caller executes command... The receiver's action() method is called...Copy the code