Introduction
Command mode, I feel "command" is the task, executed the command to complete a task. In other words, the command is a task, and we do not know from this name who the issuer and the recipient are, and for what? Because we do not care who they are, the person who issued the order, can continue to do other things, accept the order of the people to carry out the task, do not need you to give orders, but also to supervise us to complete, as long as we complete the task is qualified on the line. This behavior is "decoupling", the command pattern is used relatively little, generally in the actual project development after the discovery of the need to use when we are implemented by refactoring. In real life, we also use this design pattern, for example: we go to eat big Pai, to shop told waiter to dish beer crayfish, grilled fish one, a box of beer, after a will tell waiter don't bake fish, here we do not need to care about specific is which chef stir-fry, just to tell the waiter what we need to be able to
Introduction to Command mode
Definition of the command pattern
Encapsulates a request as an object, allowing you to parameterize the customer with different requests, queue requests or log requests, and support actions that can be undone
Structure diagram of the command pattern
The composition of the command pattern
As you can see from the structure diagram of the command pattern, it involves five roles, namely:
(1), Customer role (client): Creates a specific command object and sets the recipient of the Command object. Note that this is not our regular client, but the assembly of the Command object and the receiver, and perhaps it would be better to refer to this client as the assembler, since the client that actually uses the command is triggering execution from Invoker.
(2), command role: declares an abstract interface that is implemented for all specific command classes.
(3), the specific command role (concretecommand): Command Interface Implementation object, is the implementation of "virtual", usually hold the receiver, and invoke the function of the receiver to complete the operation of the command to do.
(4), requestor role (Invoker): requires the Command object to execute the request, usually holds the Command object and can hold many command objects. This is where the client actually triggers the command and asks the command to perform the appropriate action, which is equivalent to using the Command object's entry.
(5), Recipient role (receiver): receiver, the object that actually executes the command. Any class can become a recipient, as long as it can implement the appropriate functionality that the command requires.
Code implementation of the command pattern
First Edition no mode
classprogram {Static voidMain (string[] args) {Barbecuer boy =NewBarbecuer (); Boy. Bakemutton (); Boy. Bakemutton (); Boy. Bakemutton (); Boy. Bakechickenwing (); Boy. Bakemutton (); Boy. Bakemutton (); Boy. Bakechickenwing (); Console.read (); } }// skewers Public classBarbecuer {//Roasted lamb Public voidBakemutton () {Console.WriteLine ("Roast kebabs!"); }//Grilled chicken wings Public voidBakechickenwing () {Console.WriteLine ("Grilled chicken wings!"); } }
View Code
This way you can see that the sender of the command will be strongly coupled to the command receiver.
Second Edition introduces command mode
//Client classprogram {Static voidMain (string[] args) {//Pre-opening preparationBarbecuer boy =NewBarbecuer (); Command BakeMuttonCommand1 =NewBakemuttoncommand (boy); Command BakeMuttonCommand2 =NewBakemuttoncommand (boy); Command BakeChickenWingCommand1 =NewBakechickenwingcommand (boy); Waiter girl =NewWaiter ();//Open customer orderGirl. Setorder (BAKEMUTTONCOMMAND1); Girl. Setorder (BAKEMUTTONCOMMAND2); Girl. Setorder (BAKECHICKENWINGCOMMAND1);//After the order is closed, inform the kitchenGirl. Notify (); Console.read (); }//Waiter Public classWaiter {Privateilist<command> orders =NewList<command> ();//Set up orders Public voidSetorder (Command command) {if(command.) ToString () = = "Command mode. Bakechickenwingcommand") {Console.WriteLine ("Waiter: Chicken Wing No, please order other barbecue. "); }Else{orders. ADD (command); Console.WriteLine ("Add Order:"+ command. ToString () + "Time:"+ DateTime.Now.ToString ()); } }//Cancel Order Public voidCancelorder (Command command) {orders. Remove (command); Console.WriteLine ("Cancel Order:"+ command. ToString () + "Time:"+ DateTime.Now.ToString ()); }//Notification full execution Public voidNotify () {foreach(Command cmdinchOrders) {cmd. Excutecommand (); } } }//Abstract commands Public Abstract classCommand {protectedBarbecuer receiver; PublicCommand (Barbecuer receiver) { This. receiver = receiver; }//execute command Abstract Public voidExcutecommand (); }//Kebab order classBakemuttoncommand:command { PublicBakemuttoncommand (Barbecuer Receiver):Base(receiver) { } Public Override voidExcutecommand () {receiver. Bakemutton (); } }//Grilled chicken wings command classBakechickenwingcommand:command { PublicBakechickenwingcommand (Barbecuer Receiver):Base(receiver) { } Public Override voidExcutecommand () {receiver. Bakechickenwing (); } }// skewers Public classBarbecuer { Public voidBakemutton () {Console.WriteLine ("Roast kebabs!"); } Public voidBakechickenwing () {Console.WriteLine ("Grilled chicken wings!"); } }
View CodeImplementation scenarios for the command pattern
You can consider using the command pattern in the following scenarios:
- The system needs to support undo (undo) of the command. The Command object can store the state, and when the client needs to undo the effect of the command, it can call the Undo method to undo the effect of the command. The Command object can also provide a redo method for the client to re-implement the command effect when needed.
- The system needs to specify the request at different times and queue the request. A Command object and the original request issuer can have a different life cycle. This means that the issuer of the original request may no longer exist, and the command object itself may still be active. At this point the recipient of the command can be local or another address on the network. Command objects can be routed serially to the recipient.
- If a system is going to update all the data messages in the system to the log, so that when the system crashes, it is possible to re-invoke the method to execute these commands one at a time, based on the log's update command to read back all the data, to restore the data updates that the system made before the crash.
- The system needs to use the command mode as an alternative to the "CallBack (callback)" in the object-oriented system. Callback is to register a method first, and then call the method later.
Command Pattern pros and cons
The command pattern enables a low-coupling between one and the receiving side of the command, which has the following advantages:
- The command mode makes it easy for new commands to be added to the system.
- You can design a command queue to implement undo and redo operations on the request.
- It is easier to write commands to the log.
- You can aggregate command objects together and synthesize them into composite commands. The application of synthetic command-style synthesis mode.
Disadvantages of the command pattern:
- Using command mode may cause the system to have too many specific command classes. This makes the command pattern impractical in such a system.
Summarize
The command pattern can be called easily to design a command queue, and secondly, it can be easier to log the command in case of need, and thirdly, to allow the party accepting the request to veto the request. Finally, the cancellation and redo of the request can be implemented easily, and the new specific command class will not affect the other classes, so it is easy to add a new specific command class, and the command pattern divides the object that requests an operation with the object that knows how to perform an operation.
Never let yourself stand--
C # design Pattern series: Command pattern