Noon is coming, order a takeaway to continue to move the brick, open the software to choose green pepper fried meat cover code rice, look at the options: Coke, Wang Laoji… Working for a job is fun enough without happy water, but you can choose shredded carrots, order and pay and wait for your meal to be delivered.

This intermediate process actually includes many steps: the platform processes the request and generates the order → the restaurant reception desk receives the order, the kitchen arranges the chef to cook according to the order content → the platform arranges the rider to plan the route to the restaurant to pick up the meal -> the rider delivers the meal and so on. You just click a button to trigger a command, and regardless of the process, the actual stir-fry ends up being made by a chef in the restaurant or, of course, a stir-fry robot.

This is the basic concept of the command pattern: a request (‘ Make a green pepper stir-fry ‘) is packaged, triggered by another object (‘ the restaurant front desk ‘) and actually performed by the specific recipient (‘ the cook ‘). The requester doesn’t interact directly with the receiver, just like you don’t know which robot will end up cooking your chili stir-fry.

1. Command mode definition

The command pattern is defined in Head First design Pattern: The command pattern encapsulates “requests” into objects so that other objects can be parameterized with different requests, queues, or logs. The command mode also supports undoable actions.

Command pattern is a behavior design pattern that transforms a request into a single object, a command, that contains all the information related to the request (generally including ① the parameters required to execute the command and ② the object that actually executes the command).

Since the command object contains the elements required to execute the request, which is equivalent to encapsulating the method receiver, method name and parameters in the original method call receiver.dosomething (parameters) in an object, we can realize parameterization of the method and then execute it at the appropriate time. In this way, we can delay the execution of the request, and we can store the command object in the queue and implement the corresponding undo method, so as to achieve the purpose of the undo operation.

2. Command mode class diagram

Here is a command pattern class diagram on refactoringguru.cn (the text editor is used as an example, so there is a CopyCommand, as well as the editor and button) :

Tip: You can start with a node in the class diagram that points to more/less other nodes.

It can be seen from the class diagram that the Client relies on the most objects, and there is no node pointing to the Client. The client creates a concrete command, CopyCommand, configures the receiver of the command to be the editor, and then associates the command with a button control as the sender. When the button is clicked, the command is triggered to execute the excute() method, which in turn implements various specific requests receiver.operation(params) through the receiver within the method. Check out the original website, refactoringGuru.cn, for more details.

Role in command mode

role What do you do What not to do
1️ Sender/Invoker The command execution is triggered Do not create commands do not directly access command receivers to send requests
2️ retail Command (protocol or interface) Generally, only the method of executing a command is defined, and the public parameters or dependent objects required by all specific commands are defined. No concrete implementation is provided
3️ ConcreteCommand ConcreteCommand Implement command methods to execute specific requests:

1. Pass the request to the receiver

2. Maintain additional parameters and dependent objects required to complete the current request
4️ Receiver Complete the actual details of specific work tasks
5️ retail Client 1. Create a recipient

2. Create a command and configure the receiver

3. Create a sender and run the command

If you follow the definition of the command pattern strictly, consider that the take-out order examples mentioned at the beginning do not follow the command pattern exactly (some books also use take-out or dining out as examples). Because the command in the command mode should contain the receiver, the information of takeout order should contain the ordering user information (ordering time, price information, delivery address), restaurant information, dish information, delivery personnel information, etc., but generally does not include the final receiver – the cook who really cooks.

So if you’re serious, allowing the option to designate a specific chef when ordering comes close to the original definition of command mode.

Or, in the scene of ordering takeout, we no longer pay attention to the command of “finishing the production of dishes”, but simplify and adjust the command of “delivering takeout”, ignoring the production process of the restaurant and the process of assigning riders on the platform. When customers place an order, the client creates a specific command: ‘go to one place to pick up something and send it to another place, and configure the receiver – the rider assigned by the platform’. The platform triggers the command as the sender, and the delivery work is actually completed by the specific rider.

3. Advantages and disadvantages of command mode

According to the class diagram and the responsibility description of each role, it can be seen that almost every role is only responsible for one thing. The recipient may have a relatively complicated internal detail process, but it can also be summarized as a task. This is also a reflection of the principle of “single responsibility”.

The client as the outermost ‘organizer, in the real business systems generally belong to the GUI layer, and the sender command object will request and related information are encapsulated, generally belong to logic layer and the recipient, by using command pattern can be “sends the request object” and “receiving / *’ * separated perform the requested object, realize the decoupling. Think of the reverse, associating controls in the GUI layer directly with implementation methods in specific commands. Over time, changes in business logic that require additional tuning parameters, or need to be reused by controls in another class to achieve the same functionality, or changes in the specific implementation of the business logic may result in uI-layer code adjustments. Of course, these problems can be mitigated in other ways, such as adding adjustment parameters – you can encapsulate the parameters with a model; Control reuse in another class – you can move an implementation method to a separate object from which the method can be invoked. But if you think about it, adding a command protocol to define a command execution method, making the object follow the protocol and implement the method, and then configuring the other objects and parameters needed to execute the method, isn’t that part of the command pattern?

On the other hand, if there are no major changes or functionality extensions foreseen in the Click control to execute specified methods application, such as the many commands (copy commands, paste commands, save commands, cancel commands, etc.) that reFactoringGuru’s text editor requires, Or the example of a multifunctional remote control in Head First design Mode that dynamically adjusts the commands attached to each remote control button, there is no need for command mode.

To summarize the advantages of command mode:

  • Follow the “single responsibility principle” : reduce coupling between the GUI layer (which triggers commands) and the business logic layer (which executes specific requests).
  • Follow the “open closed rule” : You can extend and add new commands without modifying existing code.
  • “Combine more and use less inheritance” : It is convenient to combine multiple commands to achieve complex functions.

There are also some disadvantages:

  • There is obviously a relative increase in code, especially in simple businesses. (Using design patterns generally increases code/complexity in exchange for architectural neatness, as in algorithms that trade space for time.)

Refactoringgur:

  • You need to parameterize an object with an operation, and then you can save and pass commands.
  • Operations need to be queued, performed remotely, or delayed.
  • Rollback is required.

4. Command mode at work

Less seriously, our daily work is an exercise in command patterns:

① The sender, the leader, is responsible for arranging the work, that is, triggering the execution of the work.

② Command, work agreement, definition to complete the work method, don’t forget to learn after work.

③ Specific commands, a variety of different work content, demand research, prototype design, UI design, coding, testing and so on.

④ The receiver, the front-line tool person, is responsible for completing the specific work.

⑤ Client, boss, create commands such as complete the project, configure several recipients, and associate with the sender.

So, what’s your role? Comments are welcome.

In fact, almost every action we click to open the software itself and perform on an electronic device triggers a command as a sender. We don’t care about the details of how the system handles the implementation response, just triggers the command, literally everywhere.

reading

Design Mode Adapter mode in iOS

Practice: Implementing a smart home controller in Swift/SwiftUI

reference

  1. Refactoringguru.cn – Command mode: contains an example of a text editor that supports undo, the advantages and disadvantages of command mode, implementation methods, and comparison with other modes. Meanwhile, this website systematically reviews 22 design modes, and supports Chinese version.
  2. Head First Design Mode 6. Command mode. You can learn about using macro commands.