Command Pattern (Command Pattern), to give you the first feeling, is to send commands to the program, such as: start, pause, and then the program according to the received commands directly on the execution.
This is a relatively narrow understanding, so let's look at the official definition of command mode:
Encapsulating a request into an object separates the responsibility for issuing the request from the responsibility for executing it. This allows communication between the two through the command object, which makes it easy to store, pass, call, add, and manage the command object.
One is too narrow and the other too obscure. (Anti-theft link: this article first appeared from /jilodream/ )
My understanding of the command pattern is this: we encapsulate the request parameters, as well as the request's execution logic, dependent objects, etc., in an object, push this object to the execution engine, and the execution engine drives the execution. We can better encapsulate logic and manage logic through the command pattern.
It is one of the 23 object-oriented design patterns and belongs to the scope of behavioral patterns.
Let's look at one such example:
job interface class
1 package ; 2 3 /** 4 * @discription 5 */ 6 public interface IWorkCommand { 7 8 String getWorkName(); 9 10 void execute(); 11 }
Driver job family
1 package ; 2 3 import ; 4 import .slf4j.Slf4j; 5 6 /** 7 * @discription 8 */ 9 @AllArgsConstructor 10 @Slf4j 11 public class DriverWork implements IWorkCommand { 12 13 private String name; 14 15 @Override 16 public String getWorkName() { 17 return "Driver: " + name; 18 } 19 20 @Override 21 public void execute() { 22 ("start invoke {} work", getWorkName()); 23 ("Delivery of goods to a named destination"); 24 ("Clean the car."); 25 ("Return the automobile to the place where it was parked."); 26 } 27 }
Programmer job class
1 package ; 2 3 import ; 4 import .slf4j.Slf4j; 5 6 /** 7 * @discription 8 */ 9 10 @AllArgsConstructor 11 @Slf4j 12 public class ProgrammerWork implements IWorkCommand{ 13 14 private String name; 15 @Override 16 public String getWorkName() { 17 return "programmer: "+name; 18 } 19 20 @Override 21 public void execute() { 22 ("start invoke {} work", getWorkName()); 23 ("Fixing the problems left over from yesterday..."); 24 ("Completion of today's development work..."); 25 ("Optimizing system performance and stability..."); 26 } 27 }
Implementation Center
1 package ; 2 3 /** 4 * @discription 5 */ 6 public class InvokeCenter { 7 public void invokeWork(IWorkCommand workCommand) { 8 9 (); 10 } 11 }
main category
1 package ; 2 3 /** 4 * @discription 5 */ 6 public class PatternMain { 7 public static void main(String[] args) { 8 IWorkCommand programmerWork = new ProgrammerWork("Little P."); 9 IWorkCommand driverWork = new DriverWork("Little d."); 10 InvokeCenter invokeCenter = new InvokeCenter(); 11 (driverWork); 12 (programmerWork); 13 } 14 }
The output looks like this:
Connected to the target VM, address: '127.0.0.1:52437', transport: 'socket' 15:57:07.856 [main] WARN - start invoke Driver: small d work 15:57:07.866 [main] WARN - Transportation of goods to designated destinations 15:57:07.866 [main] WARN - Cleaning the car 15:57:07.866 [main] WARN - Returning the car to the parking place 15:57:07.867 [main] WARN - start invoke programmer: small p work 15:57:07.867 [main] WARN - Fixing issues left over from yesterday. 15:57:07.868 [main] WARN - Completing today's development work. 15:57:07.868 [main] WARN - Optimize system performance and stability. Disconnected from the target VM, address.'127.0.0.1:52437', transport: 'socket' Process finished with exit code 0
In this example, instead of executing various specific tasks directly, we encapsulate them all into a single section of methods, which are executed uniformly by the execution engine.
Isn't this logic similar to the logic of multithreading by instantiating a Thread? (See this article)
Yes, command mode is applied in multi-threaded execution. (Anti-theft link: this article first appeared from /jilodream/ )
We combine this with the command model and can see that this structure has roughly these 3 roles:
1, an abstract command interface (abstract class), in this case , he used to agree on where to put the method we want to execute, how to execute. We generally call the abstract command class Command
2, the implementation of the abstract command implementation class, here is, we generally through the writing of this class, to achieve the logic we want. We generally call the concrete command class Concrete Command
3, the invoker, here is, we generally through the invoker to store and execute the command, generally also known as the requestor / invoker invoker
In addition to that, there's another character
The realizer (Receiver), a role that is hidden a bit deeper in our example, is the log object, that is, the command object, that actually performs the logical operation.
Note that the invoker does not directly hold the implementer, there is no coupling between the two, it indirectly holds the caller by holding the command object, which indirectly drives the caller. This allows the invoker not to care about the specific business (e.g., the thread pool never directly holds a reference to the implementation object, but only the corresponding execution method (run()), which organizes the logic and decoupling).
The class diagram probably looks like this:
Some of you have asked if it's okay for me to rely directly on the caller and then call certain methods of the caller to implement the logic I need.
The answer is yes, but what do you do if a third party wants to execute your logic, or if you need to give that logic to a third party to handle execution at a specific time?
That's when you need to encapsulate this logic you've implemented into an object and hand it off to someone else, and that's when it ends up becoming a manifestation of the command pattern again.
In addition to decoupling, the command pattern has the added benefit of orchestrating and managing business logic (commands).
As an example: sometimes a business we're trying to do consists of several related things, and there's no order of precedence between things.
For example, if we go to the grocery store to buy a bottle of Coke, we need to do it:
1. Take a Coke.
2. Payment
At this point we can encapsulate each thing individually into a command, the entire business contains commands, packaged and thrown to the execution engine, so it is not very good to deal with the business.
Business A has to do: a,b,c three commands.
B business to do: a,c,d,e four commands
We just define each command and then encapsulate a few things (commands) that need to be done for each piece of business so that the faceted object design feel comes out right away.