Design mode - command mode

Posted by lobski on Sat, 25 Dec 2021 16:00:35 +0100

Related links:

[design mode] column: [design mode] column

Relevant examples can be downloaded: Examples of common Java design patterns

Command mode

Command Pattern is a data-driven design pattern, which belongs to behavioral pattern. The request is wrapped in the object in the form of command and passed to the calling object. The calling object looks for the appropriate object that can process the command, passes the command to the corresponding object, and the object executes the command.

Encapsulating a request as an object separates the responsibility of issuing the request from the responsibility of executing the request. In this way, the two communicate through the command object, which is convenient to store, transfer, call, add and manage the command object.

advantage

  • By introducing middleware (abstract interface), the coupling degree of the system is reduced

  • It has good expansibility, is very convenient to add / delete commands, does not affect other classes, and meets the "open close principle"

shortcoming

  • A large number of specific command classes may be generated. Because each specific operation needs to design a specific command class, which will increase the complexity of the system

  • The result of the command mode is actually the execution result of the receiver, but in order to architecture, decouple the request and implementation in the form of commands, The introduction of additional type structure (the interface between the requestor and the abstract command) increases the difficulty of understanding. However, this is also a common problem of design patterns. Abstraction will inevitably increase the number of classes. Code separation must be more difficult to understand than code aggregation.

Role of command mode

Command mode can abstract the relevant operations in the system into commands, separating the caller from the implementer.

The main roles included in the command mode are as follows:

Abstract Command class (Command) role

Declare the interface to execute the command, and have the abstract method execute() to execute the command.

Concrete Command role

It is the concrete implementation class of the abstract command class. It has the receiver object and completes the operation to be executed by calling the receiver's function.

Implementer / Receiver role

Execute the relevant operations of the command function, which is the real implementer of the specific command object business.

Caller / requester role

It is the sender of the request. It usually has many command objects and executes the relevant request by accessing the command object. It does not directly access the receiver.

Sample code

Implementer / receiver

Considering that there may be multiple receivers, it is necessary to define an abstract collection of all features - Abstract receivers

/**
 * Command mode - implementer / receiver role
 *
 * (Define an abstract recipient because there may be multiple recipients)
 *
 */
public abstract class Receiver {
    /**
     * Abstract the receiver and define the tasks that each receiver must complete
     */
    public abstract void doSomeThing();

}

The specific receiver code is as follows:

/**
 * Command mode - implementer / receiver role
 *
 * (Define specific recipients)
 *
 */
public class ConcreteReciver1 extends Receiver{
    @Override
    public void doSomeThing() {
        System.out.println("Receiver 1 is working");
    }
}

/**
 * Command mode - implementer / receiver role
 *
 * (Define specific recipients)
 *
 */
public class ConcreteReciver2 extends Receiver{
    @Override
    public void doSomeThing() {
        System.out.println("Receiver 2 is working");
    }
}

Abstract command class

/**
 * Command pattern - Abstract command class
 *
 */
public abstract class Command {

    /**
     * Execute commands, each command must be executed
     */
    public abstract void execute();
}

Specific command class

/**
 * Command mode - specific command classes
 *
 */
public class ConcreteCommand1 extends Command{

    // Build recipient object
    private Receiver receiver;

    /**
     * Constructor, specifying the recipient
     * @param receiver
     */
    public ConcreteCommand1(Receiver receiver) {
        this.receiver = receiver;
    }

    /**
     * Execute command
     */
    @Override
    public void execute() {
        // The recipient completes the task
        this.receiver.doSomeThing();
    }
}
/**
 * Command mode - specific command classes
 *
 */
public class ConcreteCommand2 extends Command{

    // Build recipient object
    private Receiver receiver;

    /**
     * Constructor, specifying the recipient
     * @param receiver
     */
    public ConcreteCommand2(Receiver receiver) {
        this.receiver = receiver;
    }

    /**
     * Execute command
     */
    @Override
    public void execute() {
        // The recipient completes the task
        this.receiver.doSomeThing();
    }
}

Caller / requester

/**
 * Command mode - caller
 *
 */
public class Invoker {
    // Build command object
    private List<Command> commands = new ArrayList<>();

    /**
     * Specify the command to execute
     * @param command
     */
    public void setCommand(Command command) {
        commands.add(command);
    }

    /**
     * Execute command
     */
    public void action() {
        // Loop through all commands
        commands.forEach(command -> {
            command.execute();
        });
        // Clear executed commands
        commands.clear();
    }
}

Test class

/**
 * Command mode
 *
 */
public class CommandPatternDemo {

    public static void main(String[] args) {
        // Declare caller Invoker
        Invoker invoker = new Invoker();
        // Define recipient 1
        Receiver receiver1 = new ConcreteReciver1();
        Receiver receiver2 = new ConcreteReciver2();
        // Define command 1 and send it to receiver 1
        Command command1 = new ConcreteCommand1(receiver1);
        Command command2 = new ConcreteCommand2(receiver2);
        // Leave the command to the caller to execute
        invoker.setCommand(command1);
        invoker.setCommand(command2);
        invoker.action();
    }

}

Conclusion

1. See more about design patterns [design mode] column

2. Relevant example codes can be downloaded: Examples of common Java design patterns

PS:   [ Examples of common Java design patterns Included in] [design mode] column The code involved in the code can be downloaded by students who need the code. If you have downloaded it before, you don't need to download it again~

If the above contents are incorrect or need to be supplemented, please consult more and update and correct them in time~

Welcome to comment ~ thank you for your praise~

Topics: Java Programming Design Pattern