Preface:
This chapter takes the encapsulation into a whole new realm and encapsulates the method invocation. By encapsulating the method call, the operation block is packaged and formed. The object that calls this operation does not need to know how it is done, but it is OK to know how to do it using the method of wrapping.
1 real-world scenario applications
Now there is a remote control, the remote control has 7 slots to be programmed, you can put a different device on each slot, and then control it with a button, these seven slots have their own "on" "Off" button, there is a whole use of the undo button, will undo the last button action.
1.1 Creating the first Command object 1.1.1 defining a command interface
Public Interfacecommand { void Execute (); }
1.1.2 Implement a command to turn on the light
Publicclass Light//Lamp class {public void on () { System.Console.WriteLine ("Lights are on !"); } public void Off () { System.Console.WriteLine ("Light is OFF!");} public class lightoncommand:command//implementation of the lights command { private light; Public Lightoncommand (Light) { this.light = light; } public void Execute () {light . On (); } }
1.1.3 Using Command objects
public class Lightcontrol { Privatecommand soft; publicvoid setcommand (command cmd) { soft= cmd;//set Command object } publicvoid buttonwaspressed () { Soft. Execute ();//method that invokes the command object }}
1.1.4 Simple test
Lightcontrol Lightcontrol = new Lightcontrol ();//The caller of the analog command lightlight = new Light ();//Create a Lamp object as the receiver of the command Lightoncommand Lightoncommand = new Lightoncommand (light);//Create a command and pass the recipient to it Lightcontrol.setcommand (Lightoncommand);// Pass the command to the caller lightcontrol.buttonwaspressed ();//Analog Trigger button
1.2 Implementing the remote control
public class Remotecontrol {command[] oncommands;//definition Open command array command[] offcommands;//define closed command array p Ublic Remotecontrol () {oncommands = new command[7]; Offcommands = new Command[7]; Command Nocommand = Newnocommand (); for (int i = 0; i < 7; i++) {Oncommands[i] = nocommand;//Initialize command Array (default is no command) of Fcommands[i] = Nocommand; }}//Set the command to the corresponding controller public void SetCommand (int index,command oncommand, command Offcommand) { Oncommands[index] = OnCommand; Offcommands[index] = Offcommand; }//Trigger open Controller public void onbuttonwaspressed (int index) {Oncommands[index]. Execute (); }//Trigger off Controller public void offbuttonwaspressed (Intindex) {Offcommands[index]. Execute (); } public override string ToString () {StringBuilder str = newStringBuilder (); Str. Append ("\ n------remotecontrol------\ n"); for (int i = 0; I <onCommands.Length; i++) {str. Append ("[Solt" +i + "]" + oncommands[i]. GetType (). FullName + "" +offcommands[i]. GetType (). FullName + "\ n"); } return str. ToString (); } }
1.3 Implementing other Controllers
Turn off the lights command public Classlightoffcommand:command {Privatelight light; Publiclightoffcommand (light) {this.light = light; } publicvoid Execute () {light. Off (); } publicvoid Undo () {light. On (); }}//Open the Fan command public class Ceilingfanoncommand:command {Ceilingfan ceilingfan; Intprespeed; Publicceilingfanoncommand (Ceilingfan ceilingfan) {this.ceilingfan = Ceilingfan; } publicvoid Execute () {Ceilingfan.on (); } publicvoid Undo () {Ceilingfan.off (); }}//Turn off the fan command public Classceilingfanoffcommand:command {Ceilingfan Ceilingfan; Publicceilingfanoffcommand (Ceilingfan ceilingfan) {this.ceilingfan = Ceilingfan; } publicvoid Execute () {Ceilingfan.off (); } publicvoid Undo () {CeilIngfan.on (); }}//Open the garage door command public Classgaragedooroncommand:command {Garagedoor Garagedoor; Publicgaragedooroncommand (Garagedoor garagedoor) {this.garagedoor= garagedoor; } publicvoid Execute () {Garagedoor.on (); } publicvoid Undo () {Garagedoor.off (); }}//close the garage door command public Classgaragedooroffcommand:command {Garagedoor Garagedoor; Publicgaragedooroffcommand (Garagedoor garagedoor) {this.garagedoor = Garagedoor; } publicvoid Execute () {Garagedoor.off (); } publicvoid Undo () {Garagedoor.on (); }}//Open cd command public Classsterecdoncommand:command {STERECDSTERECD; Publicsterecdoncommand (Sterecd sterecd) {this.sterecd = STERECD; } publicvoid Execute () {Sterecd.on (); } publicvoid UnDo () {Sterecd.off (); }}//Close the CD command public Classsterecdoffcommand:command {STERECDSTERECD; Publicsterecdoffcommand (Sterecd sterecd) {this.sterecd = STERECD; } publicvoid Execute () {Sterecd.off (); } publicvoid Undo () {Sterecd.on (); } }
1.4 Simple test
Remotecontrolremotecontrol = new Remotecontrol (); Ceilingfan Ceilingfan = Newceilingfan ("Living");//Create fan object Garagedoor Garagedoor = Newgaragedoor ();//Create garage door object STERECD STERECD = new STERECD ();//Create a CD Object light = new Lights ();//Create Lamp object Lightoncommand Lightonco Mmand = Newlightoncommand (light);//Create the Turn-on command Lightoffcommand Lightoffcommand =new Lightoffcommand; Create a light off command Ceilingfanoncommandceilingfanon = new Ceilingfanoncommand (Ceilingfan); Create an open fan command ceilingfanoffcommand ceilingfanoff= new Ceilingfanoffcommand (Ceilingfan);//create off Fan command garaged Ooroncommand Garagedooron =new Garagedooroncommand (Garagedoor);//Create Open Fan command Garagedooroffcommand garageDoorOff= n EW Garagedooroffcommand (Garagedoor);//create close fan command Sterecdoncommand Sterecdon = Newsterecdoncommand (STERECD);//Create Open cd command Sterecdoffcommand Sterecdoff = Newsterecdoffcommand (STERECD);//Create close CD command Remotecontrol.setcomman D (0,lightoncoMmand, Lightoffcommand);//Set the light command to the corresponding controller Remotecontrol.setcommand (1,ceilingfanon, Ceilingfanoff); Set the light command to the corresponding controller Remotecontrol.setcommand (2,garagedooron, Garagedooroff); Set the garage door command to the corresponding controller Remotecontrol.setcommand (3,sterecdon, Sterecdoff); Set the CD command to the corresponding controller remotecontrol.onbuttonwaspressed (0); remotecontrol.offbuttonwaspressed (0); remotecontrol.onbuttonwaspressed (1); remotecontrol.offbuttonwaspressed (1); Remotecontrol.onbuttonwaspressed (2); Remotecontrol.offbuttonwaspressed (2); Remotecontrol.onbuttonwaspressed (3); Remotecontrol.offbuttonwaspressed (3);
1.5 Implement Undo Command 1.5.1 Modify command interface, add Undo () method
Public Interfacecommand { void Execute (); void Undo ();//New Undo Method}
1.5.2 Modify the command to implement the Undo method
public class Lightoncommand:command { private light light; Public Lightoncommand (Light) { this.light = light; } public void Execute () {light . On (); } public void Undo ()//Implement Undo method {Light . Off (); }}
Other classes are modified in turn
1.5.3 Modify Remotecontrol class, add Command object record previous action
public class Remotecontrolwithundo {command[] oncommands; Command[] Offcommands; commandundocommand;//creates a command object used to record commands executed in the previous step Publicremotecontrolwithundo () {oncommands = new Comm AND[7]; Offcommands = new Command[7]; Command Nocommand = new Nocommand (); for (int i = 0; i < 7; i++) {oncommands[i] = Nocommand; Offcommands[i] = Nocommand; } Undocommand = Nocommand; }................. publicvoid onbuttonwaspressed (int index) {Oncommands[index]. Execute (); Undocommand = oncommands[index];//record Open command} publicvoid offbuttonwaspressed (int index) {OFFC Ommands[index]. Execute (); Undocommand = offcommands[index];//record Close command} publicvoid undobuttonwaspressed ()//Perform undo {Undoc Ommand. Undo (); } ...... ...... }
1.6 Macro Commands
Let the remote control have party mode, that is, a button can synchronously invoke multiple commands, this is called Macro command.
public class Macrocommand:command { command[] commands;//defines the command array to receive the incoming command public Macrocommand (command[ ] commands) { this.commands = commands; } public void Execute ()//batch processing multiple commands (that is, an array of commands passed in at initialization time) {for (int i = 0; I <commands. Length; i++) Commands[i]. Execute (); } public void Undo () {for (int i = 0; I <commands. Length; i++) Commands[i]. Undo (); } }
2 Defining the command pattern
The command pattern encapsulates "requests" into objects so that different requests, queues, or logs can be used to parameterize other objects. The command mode also supports the revocable operation.
To define a command pattern class diagram:
3 more uses of the command mode 3.1 queue requests
command to package the operation block, and then spread it, even after the command object has been created for a long time, the operation can still be called, and even can be called in different threads, we can use this feature to derive the application, such as: daily arrangement, thread pool, task queue and so on.
The work queue class is completely decoupled from the object being evaluated. They can be placed inside the queue as long as they are objects that implement the command pattern, and invoke the Execute () method of the object when the thread is available.
3.2 Log Requests
Some applications require that we log all actions to the logs, and after the system freezes, recall these actions back to their previous state, which is supported by the command pattern.
There are many action applications that call large data structures that cannot be stored quickly every time a change occurs, and by using logging, we can record all the actions after the last checkpoint and, if the system is present, you can apply them from checkpoints. For more advanced applications, these techniques can be extended to transactional processing, where a whole group of operations must be completed or nothing is done.
3 Summary
The command mode decouples the object that makes the request and the object that executes the request.
The decoupling between the two is communicated through the Command object, which encapsulates the receiver and a set of actions.
The caller makes a request by invoking execute () of the Command object, which causes the receiver's action to be invoked.
The caller can receive commands as arguments, even dynamically at run time.
The l command can support revocation by implementing an undo () method to return to the state before execute () is executed.
The macro command is a simple extension of the command that allows multiple commands to be invoked, and the macro method can also support revocation.
The L command can also be used to implement log and transaction systems.
Head First design mode command mode (commandpattern)