23 design modes, Chapter 17: Java command mode
Definition: Encapsulate a request into an object, allowing you to parameterize the client using different requests, queue requests or record request logs, and provide command revocation and recovery functions.
Type: Behavioral Pattern
Class diagram:
The structure of command mode
As the name suggests, command mode is the encapsulation of commands. First, let’s take a look at the basic structure in the command mode class diagram:
Command class: is an abstract class that declares the commands that need to be executed. Generally speaking, an execute method must be published to the public to execute the command.
ConcreteCommand class: The implementation class of the Command class, implements the methods declared in the abstract class.
Client class: The final client calling class.
The functions of the above three classes should be easier to understand. Let’s focus on the Invoker class and Recevier class.
Invoker class: The caller is responsible for invoking commands.
Receiver class: The receiver is responsible for receiving and executing commands.
To put it bluntly, the so-called encapsulation of commands is nothing more than writing a series of operations into a method and then being called by the client. It is reflected on the class diagram. It only takes a ConcreteCommand class and Client class to complete the encapsulation of commands. Even if it goes further, in order to increase flexibility, a Command class can be added for appropriate abstraction. What is the function of this caller and receiver?
In fact, you can think from another perspective: if you simply encapsulate some operations as a command for others to call, how can it be called a pattern? As a behavioral model, the command mode must first achieve low coupling. Only when the coupling degree is low can flexibility be improved. The purpose of adding the caller and receiver roles is precisely for this. The general code for command mode is as follows:
class Invoker { private Command command; public void setCommand(Command command) { this.command = command; } public void action(){ this.command.execute(); } } abstract class Command { public abstract void execute(); } class ConcreteCommand extends Command { private Receiver receiver; public ConcreteCommand(Receiver receiver){ this.receiver = receiver; } public void execute() { this.receiver.doSomething(); } } class Receiver { public void doSomething(){ System.out.println("Recipient-Business Logic Processing"); } } public class Client { public static void main(String[] args){ Receiver receiver = new Receiver(); Command command = new ConcreteCommand(receiver); //The client directly executes the specific command method (this method is consistent with the class diagram) command.execute(); //The client executes the command through the caller Invoker invoker = new Invoker(); invoker.setCommand(command); invoker.action(); } }Through the code we can see that when we call, the execution timing is first the caller class, then the command class, and finally the receiver class. In other words, the execution of a command is divided into three steps, and its coupling degree is much lower than encapsulating all operations into a class. This is the essence of the command pattern: separate the caller of the command and the executor so that both parties do not have to care about how the other party operates.
Advantages and disadvantages of command mode
First of all, the command mode is very encapsulation: each command is encapsulated, and for the client, the corresponding command is called as much as the function is needed without knowing how the command is executed. For example, there is a set of file operation commands: create a new file, copy a file, and delete a file. If these three operations are encapsulated into a command class, the client only needs to know that there are these three command classes. As for the logic encapsulated in the command class, the client does not need to know.
Secondly, the command mode has a good scalability. In the command mode, the most basic encapsulation of operations in the receiver class, and the command class secondary encapsulation of these basic operations. When adding new commands, the writing of the command class is generally not from scratch. There are a large number of receiver classes for call, and there are also a large number of command classes for call, and the code is very reusable. For example, in the operation of a file, we need to add a command to cut a file, and we only need to combine the two commands of copying a file and deleting a file, which is very convenient.
Finally, let’s talk about the disadvantages of the command mode, that is, if there are many commands, it will be a headache to develop. Especially many simple commands are only a few lines of code to implement. If you use the command mode, you don’t have to worry about how simple the command is, you need to write a command class to encapsulate it.
Applicable scenarios for command mode
For most request-response mode functions, it is more suitable to use the command mode. As the command mode definition says, the command mode is more convenient for implementing functions such as logging and undoing operations.
Summarize
Whether to use the mode in an occasion is a very tangled question for all developers. Sometimes, because of the foreseeing some changes in requirements, a certain design pattern is used for the flexibility and scalability of the system, but this foreseeable requirement does not. On the contrary, many unforeseeable requirements have come, resulting in the design pattern used playing the opposite role when modifying the code, so that the entire project team complained. I believe every programmer has encountered such an example. Therefore, based on the principle of agile development, when we design programs, if we can solve them well without using a certain pattern according to the current needs, then we should not introduce it, because it is not difficult to introduce a design pattern. We can do it on the system when we really need it to use it and introduce this design pattern.
Take command mode as an example. In our development, the request-response mode function is very common. Generally speaking, we will encapsulate the response operation to the request into a method. This encapsulated method can be called a command, but not a command mode. Whether this design should be raised to the height of the pattern needs to be considered separately, because if the command mode is used, the two roles of caller and receiver must be introduced. The logic originally placed in one place is scattered into three categories. When designing, it is necessary to consider whether this cost is worth it.
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.