Understanding design patterns-command patterns

Source: Internet
Author: User

Understanding design patterns-command patterns
I have learned part of the design model, but I have never studied the system. I recently bought the big talk design model from Cheng Jie and recently want to learn it systematically. When I saw the command mode, I thought it was not very easy to understand, so I searched some documents online. I found that many articles on the design pattern were somewhat different, so I wanted to write my own views on the Command pattern to deepen my understanding. If there is something wrong with the article, I hope you can put forward suggestions for improvement. Purpose: Any mode is used to solve the coupling problem in some specific scenarios, so as to achieve the effect of blocking modification and opening expansion. Command mode is no exception: the command mode is used to solve the coupling relationship between the requester and the real-time user of the command. I think there are two main advantages to solve this coupling: 1. more convenient extension of commands (note: this is not the main advantage and will be mentioned later) 2. unified Control over multiple commands (This control includes but is not limited to queue, revocation/recovery, logging, etc.) mode resolution: the classic Command mode includes four roles: Command: define the unified interface ConcreteCommand of a Command: the implementer of the Command interface, which is used to execute specific commands. In some cases, it can be directly used as the aggreger. Extends Er: the actual executor of a command. Invoker: the requester of a command. It is the most important role in command mode. This role is used to control various commands. The following describes the typical implementation of the above four roles using code, which is also the use of the command mode in most articles. Classic code implementation: 1 // <summary> 2 // Command role 3 /// </summary> 4 public interface ICommand 5 {6 void Execute (); 7} 8 9 /// <summary> 10 // ConcreteCommand role A11 /// </summary> 12 public class ConcreteCommandA: ICommand13 {14 private aggreger extends ER = null; 15 16 public ConcreteCommandA (creator er extends ER) 17 {18 this. extends ER = extends er; 19} 20 21 public void Execute () 22 {23 this. aggreger. doA (); 24} 25} 2 6 27 /// <summary> 28 /// ConcreteCommand role B29 /// </summary> 30 public class ConcreteCommandB: ICommand31 {32 private javaser explorer = null; 33 34 public ConcreteCommandB (Explorer) 35 {36 this. extends ER = extends er; 37} 38 39 public void Execute () 40 {41 this. aggreger. doB (); 42} 43} 44 45 // <summary> 46 // Cycler role 47 // </summary> 48 public class Receiver49 {50 public void DoA () 51 {52 // D OSomething53} 54 55 public void DoB () 56 {57 // DoSomething58} 59} 60 61 // <summary> 62 // Invoker role 63 /// </summary> 64 public class Invoker65 {66 private ICommand command = null; 67 68 // set command 69 public void SetCommand (ICommand command) 70 {71 this. command = command; 72} 73 // Run command 74 public void RunCommand () 75 {76 command. execute (); 77} 78} 79 80 // <summary> 81 // client call 82 // </summary> 83 public class Client84 {85 public Client () 86 {87 consumer er extends ER = new consumer Er (); 88 Invoker invoker = new Invoker (); 89 invoker. setCommand (new ConcreteCommandA (Consumer ER); 90 invoker. runCommand (); 91 invoker. setCommand (new ConcreteCommandB (aggreger); 92 invoker. runCommand (); 93} 94} classic Implementation Analysis: I don't know what it feels like after reading the above Code, anyway, after I read the above Code, the first response is indeed getting confused. I mainly think there are several questions: 1. you can run the command, but why is it a little cool to hide your pants? I can write like this: 1 public class Client2 {3 public Client () 4 {5 extends er extends ER = new extends Er (); 6 extends er. doA (); 7 receiver. doB (); 8} 9} Isn't it simpler and clearer? Two classes. 2. After inheriting the ICommand, how can I add more commands? For example, to add a command, you need to change three places: add an ICommand implementation, modify the javaser class, and modify the Client. Does this seem to have been disabled? What's more, after using the following method to write the Invoker class in some places, you need to modify the four places! 1 /// <summary> 2 /// Invoker role 3 /// </summary> 4 public class Invoker 5 {6 private ICommand commandA = null; 7 8 // set command A 9 public void SetCommandA (ICommand commandA) 10 {11 this. commandA = commandA; 12} 13 // run the A14 public void RunCommandA () 15 {16 commandA. execute (); 17} 18 19 private ICommand commandB = null; 20 21 // set command B22 public void SetCommandB (ICommand commandB) 23 {24 this. commandB = commandB; 25} 26 // Execute Command B27 public void RunCommandB () 28 {29 commandB. Execute (); 30} 31} day! This is a nightmare, and I have no idea whether to close the changes. Is it because I fully understand the command mode wrong? 3. ConcreteCommandA and ConcreteCommandB are completely coupled with the ConcreteCommandB class. What if ConcreteCommandA and ConcreteCommandB need to execute commands in different referers? I can see that my friends who have little knowledge about the design model are totally confused. In this case, they have serious doubts about their IQ, or the design model is wrong ??? But is it true? NONONONO, you can think of none. This is a classic design model. Well, let's look at what's wrong: 1. There are actually two classes. However, we should keep in mind the original intention of the command mode: decoupling the Invoker and the real-time hacker to facilitate various control over the command. For example, we want to log ConcreteCommandA, ConcreteCommandB, and a series of other commands, and the operation interval between the two commands cannot be greater than 1 second. In this case, a large number of business logic needs to be processed directly using two classes on the client. When the number of commands increases and the number of controls on each command increases, there will be a lot of changes in the Client, so the coupling will come out, but after using the command mode, we can control a series of commands, this is the encapsulation of the change point. The actual Invoker code is as follows: 1 public class Invoker 2 {3 private ICommand lastCommand = null; 4 private DateTime lastDateTime = DateTime. now; 5 6 public void RunCommand (ICommand command) 7 {8 // record operation log 9 Console. writeLine (command. getType (). name); 10 // more than 1 second, Execute Command 11 if (lastCommand = null | (Dat ETime. now-this. lastDateTime ). totalSeconds> 1) 12 {13 lastCommand = command; 14 lastDateTime = DateTime. now; 15 command. execute (); 16} 17 // if it is less than 1 second, it is not executed and 18 consoles are processed accordingly. writeLine ("the operation interval is too short! "); 19} 20} 2. add command: When the command mode is used, I feel that the biggest coupling point has changed to between the consumer er and ConcreteCommand. Of course, we can abstract the consumer er and encapsulate this change using interfaces or abstract classes, however, in actual situations, we will encounter multiple commands, for example, commands A and B, for ReceiverAB and C, for ReceiverC, in this case, how can we cope with the addition of commands? In this case, I understand that the command mode does not and does not need to solve this problem, because the operation unit of the command mode has been refined to each specific function, when adding a specific function, there is no good way to modify or disable the function implementation class (of course, you can put each function method into a class, but it is not necessary, this granularity is already small.) In fact, it is not necessary. For example, the deletion function is added to an interface, which is implemented in a worker class. Is it necessary to add a Reeciver class to add a modification function? My own answer is unnecessary. However, when all the functions of the business are modified at the same time, we can abstract the handler and extract the icycler. Implementation of different Reducers: 1 /// <summary> 2 /// ConcreteCommand role A 3 /// </summary> 4 public class ConcreteCommandA: ICommand 5 {6 private ReceiverAB extends ER = null; 7 8 public ConcreteCommandA (ReceiverAB extends ER) 9 {10 this. extends ER = extends er; 11} 12 13 public void Execute () 14 {15 this. aggreger. doA (); 16} 17} 18 19 // <summary> 20 // ConcreteCommand role B21 /// </summary> 22 public class ConcreteCommandB: I Command23 {24 private ReceiverAB receiver = null; 25 26 public ConcreteCommandB (ReceiverAB receiver) 27 {28 this. extends ER = extends er; 29} 30 31 public void Execute () 32 {33 this. aggreger. doB (); 34} 35} 36 37 // <summary> 38 // ConcreteCommand role C39 /// </summary> 40 public class ConcreteCommandC: ICommand41 {42 private ReceiverC receiver ER = null; 43 44 public ConcreteCommandC (ReceiverC receiver ER) 45 {46 th Is. extends ER = extends er; 47} 48 49 public void Execute () 50 {51 this. aggreger. doC (); 52} 53} 54 55 // <summary> 56 // Receiver role 57 // </summary> 58 public class ReceiverAB59 {60 public void DoA () 61 {62 // DoSomething63} 64 65 public void DoB () 66 {67 // DoSomething68} 69} 70 71 // <summary> 72 /// assumer role 73 /// </summary> 74 public class ReceiverC75 {76 public void DoC () 77 {78 // DoSomething79} 80} Same as worker er implementation: 1 // <summary> 2 // Command role 3 /// </summary> 4 public interface ICommand 5 {6 void Execute (); 7} 8 9 // <summary> 10 // ConcreteCommand role A 11 /// </summary> 12 public class ConcreteCommandA: ICommand 13 {14 private IReceiver extends ER = null; 15 16 public ConcreteCommandA (IReceiver extends ER) 17 {18 this. extends ER = extends er; 19} 20 21 public void Execute () 22 {23 this. recei Ver. doA (); 24} 25} 26 27 // <summary> 28 // ConcreteCommand Role B 29 /// </summary> 30 public class ConcreteCommandB: ICommand 31 {32 private IReceiver extends ER = null; 33 34 public ConcreteCommandB (IReceiver extends ER) 35 {36 this. extends ER = extends er; 37} 38 39 public void Execute () 40 {41 this. aggreger. doB (); 42} 43} 44 45 // <summary> 46 // ConcreteCommand Role B 47 /// </summary> 48 publi C class ConcreteCommandC: ICommand 49 {50 private IReceiver extends ER = null; 51 52 public ConcreteCommandC (IReceiver extends ER) 53 {54 this. extends ER = extends er; 55} 56 57 public void Execute () 58 {59 this. aggreger. doA (); 60} 61} 62 63 public interface IReceiver 64 {65 void DoA (); 66 67 void DoB (); 68} 69 70 // <summary> 71 // assumer role 72 /// </summary> 73 public class ReceiverOne: IRe Ceiver 74 {75 public void DoA () 76 {77 // DoSomething 78} 79 80 public void DoB () 81 {82 // DoSomething 83} 84} 85 86 // <summary> 87 // The assumer role 88 /// </summary> 89 public class ReceiverTwo: IReceiver 90 {91 public void DoA () 92 {93 // DoSomething 94} 95 96 public void DoB () 97 {98 // DoSomething 99} 100} 3. this question has been explained in the above answer. I will not explain it here. Use Cases: 1. the sender and executor of a command have different lifecycles. The command is not executed immediately after it is sent. 2. Various management logics are required for commands. 3. You need to support Undo/Redo operations (in this case, you can search the code online, there are many, so I will not explain it in detail here ). Conclusion: Through the above analysis, we can know the following points: 1. The command mode controls the command by decoupling the command sender and the command executor. 2. The command mode is the abstraction of functional methods, not the abstraction of objects. 3. The command mode promotes functions to objects for operations, so as to process and encapsulate multiple functions. Now, my understanding of the command mode is over. If you find any errors, I hope you can correct them. If you have any questions, you can also raise them and make progress together.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.