Command mode analysis of common design patterns

Today is the sixth chapter of the design pattern learning series, command mode !

Start with questions

  1. What is the command mode?
  2. What are the benefits of command mode?
  3. What is the usage scenario of command mode?

Command mode analysis

Simply put, the command mode is to the caller requests and receives an execution-requested separated.

To give a common example in life, for example, you go to a restaurant to order and you choose the dishes to place an order. At this time, the waiter will come over, take the menu and don’t care about anything, just give the menu to the kitchen. The kitchen prepares the dishes, the waiter Return to the customer.

In this example, the waiter is the caller of the request. She does not care what the specific order is. She only knows that the order is given to the chef (call the execution method), and the chef is the recipient of the request, and the customer is the creator of the order. , Set the order to the caller (waiter), then the customer can ask the caller to execute the order later, that is, hand the order to the kitchen.

Through the above example, you should have a certain understanding of how the classes and objects in the command mode interact. The detailed concept of the command mode is given below:

Command mode encapsulates "requests" into objects so that different requests, queues, or logs can be used to parameterize other objects. Command mode also supports undoable operations.

The key to this pattern is an abstract Command class, which defines an interface for performing operations. In its simplest form, it is an abstract execute operation. The specific Command subclass takes the receiver as an instance variable and implements the execute operation, specifying the actions taken by the receiver, and the receiver has the specific information needed to execute the request. Since this object only exposes one execute method, when this method is called, the receiver will perform these actions. From the outside, other objects don't know which receiver has performed which operations. They only know that the execute method is called to achieve the purpose of the request.

Insert picture description here

  • Client:
    This client is responsible for creating a ConcreteCommand and setting its receiver.

  • Receiver: The
    receiver knows how to perform the necessary work to fulfill this request. Any class can be a receiver.

  • ConcreteCommand:
    This is a "virtual" implementation, which binds the corresponding relationship between the action and the receiver. When the caller calls execute, the request can be made, and then ConcreteCommand calls one or more actions of the receiver.

  • Invoker:
    This caller holds a command object and calls the execute method of the command object at a certain point in time to put the request into practice.

  • Command:
    Defines the command object interface and the method of life execution. The caller only needs to hold this type of object, regardless of the specific implementation class.

Brain Power

After learning the command mode, let's look at the second question raised at the beginning of the article. What are the benefits of the command mode?

You should have the answer, which is to support decoupling between request callers and request receivers.

Undoable operation

An undoable operation means: abandon the operation and return to the state before the operation was not performed. That is, each command must support the undo operation and roll back to the state before execution.

There are two basic ideas to implement undoable operations:

  • One is the compensation type, also known as the reverse operation type. For
    example, if the undone operation is an addition function, then the realization of the undo becomes a subtraction function; similarly, the undone operation is an open function, then the realization of the undo becomes Closed function. Corresponding to our command mode is to add an undo method to Command, no matter what execute just now, undo will be reversed.
  • The other method is the storage recovery type, which
    means to record the state before the operation, and then directly restore it when you want to undo the operation.

Another scenario is that the undo button can be pressed all the time. For example, pressing it once to go back to the previous state, and pressing it twice is the previous state. How can this be achieved?

It's actually very simple. Don't just record the last executed command in the caller. Instead, use a stack structure. Every time a command is executed, it is placed on the stack, and then every time the undo button is pressed, the top command is taken out of the stack. , Execute the undo method.

Usage scenarios of command mode

This part mainly enumerates more uses of the command mode. In reality, the restaurant ordering and the button settings of the remote control that we see are all places where the command mode can flex its muscles.

The key point of the command mode is to encapsulate the request into an object, which is a command object (including a receiver and a set of actions), and then pass it back and forth, just like a normal object. Now, even long after the command object is created, the operation can still be called. In fact, it can even be called in different threads. We can use this feature to derive some applications, such as thread pools, work queues, log requests, etc.

Queue request

Imagine a work queue: you add commands at one end, and threads at the other end. The thread performs the following actions: Take a command from the queue, call its execute() method, wait for the call to complete, then discard the command object, and then take the next command...
Please note that the work queue class and the command for calculation The objects are completely decoupled. At this moment the thread may be performing financial calculations, but the next moment it is reading network data. Work queue objects don't care what they do, they only know to take out the command object and then call its execute() method. Similarly, as long as they are objects that implement the command mode, they can be put in the queue, and when the thread is available, the execute() method of this object is called.

Log request

Some applications require us to record all actions in the log, and re-call these actions to restore the previous state after the system crashes. Generally by adding two methods (store(), load()), the command mode can support this.

How do we do this? For example, for database write and update operations, each time the data changes, it is time-consuming to organize the index structure, so it will not be stored quickly every time the execution action changes. By using the log, we can write all the operations after the last checkpoint (checkpoint) to the log in order. If the system has a situation, we can reload these command objects from the disk log, and then call these objects in batches. execute method to resume these operations.

to sum up

  1. Command mode decouples the requesting object and the executing request;
  2. The decoupled two communicate through the command object. The command object encapsulates the receiver and one or a group of actions;
  3. The caller sends a request through the execute() of the command object, which will make the receiver's action be called to fulfill the request;
  4. The caller can accept the command object as a parameter, and can proceed dynamically at runtime;
  5. The command supports cancellation, the way is to return to the state before executing the execute( method by implementing an undo() method;
  6. A macro command is an extension of a command, that is, it includes a set of commands and allows one-time calling. Macro methods can also support undo;
  7. In actual operation, it is very possible to use "smart" command objects, that is, to directly implement the request without encapsulating the receiver for delegation;
  8. Commands can also be used to implement log and transaction systems;

If you do not understand the command mode, you can refer to the sample teaching code, follow the official account, and reply to the "design mode" to get it.

Reference

  1. "Head First Design Pattern"
  2. "Design Patterns: The Foundation of Reusable Object-Oriented Software"

Guess you like

Origin blog.csdn.net/taurus_7c/article/details/107436260