0x01: Introduction to command mode
In software design, we often need to send requests to some objects, but we do not know who is the recipient of the request, and do not know which operation is requested. We only need to specify the specific recipient of the request when the program runs. At this time, we can use the command mode to design.
Command mode: The request is wrapped in an object as a command and passed to the calling object. The calling object looks for a suitable object that can handle the command and passes the command to the corresponding object, which executes the command.
The UML class diagram is as follows:
Main roles are analyzed as follows:
Invoker: The caller that asks the command to perform the request, usually holds the command object, and can hold multiple command objects. This is where the client actually triggers the command and asks the command to do something, which is the equivalent of using the command object.
Command: Abstract Command. All commands that need to be executed are declared here. They can be interfaces or abstract classes.
Receiver: The Receiver that actually executes the command. Knowing how to perform the operations associated with executing a request, any class can be a recipient, as long as it can do what the command requires.
ConcreteCommand: Command interface implementation object, an implementation of “virtual”; It usually holds the receiver and invokes the receiver’s functions to do what the command wants to do.
Client: Creates a command object and sets the receiver of the command object. Note that this is not a client in the normal sense, but rather an assembly of command objects and receivers. It might be better to refer to the Client as an assembler, since the Client that actually uses the command triggers execution from Invoker.
0x02: Implementation of command mode
Receiver: This role is the role doing the work and the command should be executed as soon as it is delivered
Public class Receiver {public void action() {system.out.println (" command executed ~~~"); }}Copy the code
Command: Declares the interface/abstract class to perform the operation
public abstract class Command { protected Receiver receiver; public Command(Receiver receiver) { this.receiver = receiver; } public void execute(); }Copy the code
The ConcreteCommand class: concrete commands that are used to construct the delivery receiver. Depending on the scenario, there may be more than one ConcreteCommand class
Public Class ConcreteCommand extends Command {public ConcreteCommand(Receiver Receiver) {super(Receiver); } @override public void execute() {receiver.action(); }}Copy the code
Invoker class: receives commands and executes them
public class Invoker { private Command command; Public void setCommand(Command Command) {this.mand = Command; } public void executeCommand() {command.execute(); }}Copy the code
Command mode test code: first define a receiver, then define a command to send to the receiver, and finally declare a caller to give the command to the caller to execute
Public class Client {public static void main(String[] args) {// Define Receiver Receiver = new Receiver(); // Define a Command to send to the receiver Command Command = new ConcreteCommand(receiver); Invoker = new Invoker(); // Give the command to the caller to execute invoker.setCommand(command); Invoker.executecommand (); invoker.executecommand (); }}Copy the code
0x03: Use of command pattern in JDK and open source frameworks
Java.lang.Runable in multithreading
The Runnable interface in the JDK is equivalent to an abstract Command in Command mode. The run() method in Runnabl is equivalent to the execute() method.
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
Copy the code
Any class that implements the Runnable interface is considered a thread, equivalent to ConcreteCommand in command pattern.
Threads are invokers and provide methods such as start, Join, interrupt to control the execution of “commands” or Runnable. A Receiver, on the other hand, is an abstraction that allows programmers to freely combine with Runnale.
In fact, once the thread’s start() method is called, it is eligible to compete for CPU resources without having to write the logic to get them. Once the thread grabs CPU resources, it executes the run() method, using the Runnable interface to decouple user requests from CPU execution.
Workflow engine Activiti
Activiti is an excellent open source software, read the source code, not only understand the workflow engine implementation principle, but also increase your coding skills. All Activiti executions are executed in command mode.