The purpose of the command mode is to encapsulate a request as an object so that you can parameterize the customer with different requests. The second is to queue requests or record request logs, and supports undo operations. The following figure shows a brief description:
By encapsulating commands, the command request (caller Invoker) and the execution (Receiver) are separated and assigned to different objects, this not only decouples the caller and executor (the requester of a command does not need to know the interface of the receiver or the specific execution of the command ), it also allows you to record Command Execution records and add execution logs, making it easy to control, execute, cancel, and redo commands.
The Action of Delphi adopts this mode. Windows controls (such as buttons and menus) are callers, Action is commands, and the receiver is the implementer of the OnExecute event of Action. Of course, in order to implement the gray change of the control during the design or runtime, Delphi adds an ActionLink class hierarchy in the middle to ensure that the control's Caption can be consistent with the Action when needed, the bridge mode is used. The control hand over the communication between the control and the Action to the ActionLink. The creation of the AcionLink object adopts the factory method (the factory is the control itself ), however, it makes more clever use of the GetActionLinkClass function. The specific execution of Action adopts the event method, which further decouples the command from the receiver. In this way, the command does not need to know the receiver's interface or maintain references to the receiver, the recipient does not need to know the specific details of the command, but only needs to provide a method to handle the event that meets the requirements.
The following is the sample code:
/// <Summary>
/// Command class, which defines an operation execution interface or an interface.
/// </Summary>
Public abstract class Command_Command
{
Protected Command_Receiver _ Receiver;
Public abstract void Execute ();
Public Command_Receiver extends er
{
Get
{
Return _ Cycler;
}
Set
{
_ Cycler = value;
}
}
}
Public class Command_ConcreateCommand: Command_Command
{
Public Command_ConcreateCommand ()
{
}
Public override void Execute ()
{
If (System. Windows. Forms. MessageBox. Show ("do you want to perform this operation? "," System prompt! ",
System. Windows. Forms. MessageBoxButtons. YesNo) = System. Windows. Forms. DialogResult. Yes)
{
If (this. _ else er! = Null)
{
This. _ cycler. Action ();
}
}
}
}
Public class Command_Receiver
{
Public Command_Receiver ()
{
}
Public void Action ()
{
System. Windows. Forms. MessageBox. Show ("Command Execute! ");
}
}
Public class Command_Invoker
{
Private Command_Command command;
Public Command_Invoker ()
{
}
Public void SetCommand (Command_Command command)
{
This. command = command;
}
Public void Execute ()
{
This. command. Execute ();
}
}
Public class Command_Client
{
Public static void Test ()
{
// Create a specific command
Command_ConcreateCommand command = new Command_ConcreateCommand ();
// Create a specific Receiver
Command_Receiver r1 = new Command_Receiver ();
// Link command and Receiver
Command. Cycler = r1;
// Create a caller
Command_Invoker invoker = new Command_Invoker ();
// Set the sub-class of the caller's command
Invoker. SetCommand (command );
// Execute the call operation
Invoker. Execute ();
}
}
Summary:
If the request and execution of commands are not separated from each other and delegated to different objects, the request and execution must be completed in the same object, such as the Click Command of the Button, however, this brings about a problem. The Click logic of the Button is too complicated. Because the Button is the same, the business logic executed when different users request the Click command may be completely different, in addition, it is unrealistic to implement it through the subclass of the Button. Therefore, the request and execution responsibilities of commands must be separated as well. There are two ways to achieve separation: one is to use the callback function (the original Windows system is more common ), the second is to use events or delegation (Delphi object method), and the third is to use the command mode. 1 and 2 actually belong to the same type of processing method, and the advantage is simple (Note: although this application mode is quite common, there is also a drawback that it is difficult to separate page designers from page logic implementation, for example, the dotnet aspx page and the corresponding. due to the tight coupling between cs, it is difficult to implement the separation of uidesign and UI logic implementation. The silverlight VM aims to make up for this defect .). However, the disadvantage is that the command itself cannot be managed (execute, cancel, log, redo, and so on ). If the command itself does not need to be managed or controlled, it is better to use 2. Currently, the command processing of the interface control is basically done in this way. To manage commands, use the Command mode.
If the receiver is abstracted, the dynamic combination of commands and receivers can be realized, which is similar to the decoration mode and Policy mode.
An improvement of the command mode is to remove the receiver references in the command and use the event or delegate method to contact the receiver. If the caller is abstracted, a caller system and a command system are formed. If the contact between the two is required, a contact layer can be added. In this way, there are three relatively independent layers, delphi's Action mode is like this. This is conducive to the visual design of the system.
Note: The command mode is widely used in the current programming system, especially in the decoupling between the UI Layer and the control layer or the business logic layer. Of course, what's worse is that it increases the complexity of the system. In the mvvm mode of silverlight programming, the vm layer can be considered as a command layer, which connects the M and V layers, at the same time, the link between this layer and the page layer is no longer a traditional page and. the cs relationship is bound directly in the UI (the traditional method is to bind page events to the corresponding background. cs file, this file also exists in the mvvm mode, in addition to the default code and the code attached to the VM, There is no code, if dynamic binding V-VM, basically, only the default code is left. Therefore, the UI design does not need to consider the impact on this file at all. This makes the page design and the page implement logical separation, we can achieve separation of responsibility between uidesign and UI logic development, so as to achieve more professional design. The side effect is that many classes and interfaces need to be added.