One of the last steps to renovate a new house is to install a socket and a switch. Through the switch, you can control the opening and closing of some electrical appliances, such as electric lights or exhaust fans. When purchasing a switch, we don't know what electrical appliance it will be used to control in the future. That is to say, the switch has no direct relationship with the electric lights and exhaust fans. A switch may be used to control the electric lights after installation, it may also be used to control exhaust fans or other electrical equipment. A connection is established between the switch and the electric appliance through a wire. If the switch is turned on, the electric appliance is powered on. Otherwise, the switch is closed, the electric appliance is powered off, and the electric appliance stops working. The same switch can control different appliances through different wires, as shown in Figure 1:
Figure 1 switch and electric lamp and exhaust fan
In Figure 1, we can understand the switch as a request sender, through which the user sends an "turn on" request, and the light is the final receiver and processor of the "turn on" request, in the figure, there is no direct coupling between the switch and the electric lamp. They are connected by a wire. Different wires can be used to connect different request recipients. You only need to replace one wire, the same sender (switch) can correspond to different receivers (appliances ).
There are also many request senders and receiver objects similar to switches and appliances in software development. For example, a button may be the sender of a "Close Window" request, the button click event processing class is the recipient of the request. To reduce the Coupling Degree of the system and decouple the request sender and receiver, we can use a design pattern called the Command pattern to design the system. In the Command pattern, A new command object (similar to the wire in Figure 1) is introduced between the sender and the receiver. The request of the sender is encapsulated in the command object and the method of the receiver is called through the command object. This chapter describes the command modes used to decouple the request sender and receiver.
1. Custom function key
Developers of Sunny software company developed a desktop edition application for the company's internal OA system, which provides users with a series of custom function keys that allow users to perform quick operations. Through analysis, developers of Sunny software company found that different users may have different usage habits. When setting function keys, everyone has their own preferences, for example, some people prefer to set the first function key to "Open Help Document", while others prefer to set this function key to "minimize to tray ", to allow users to set function keys flexibly, developers provide a "function key settings" window, as shown in interface 2: Figure 2 "function key settings" Page On the interface shown in figure 2, you can bind the function key with the corresponding function, and modify the function key settings as needed, in addition, the system may add some new functions or function keys in the future. |
A developer of Sunny software company wants to use the following code to call the function key and function processing class:
// Functionbutton: function key class, request sender class functionbutton {private helphandler help; // helphandler: Help document processing class, request recipient // onclick () in functionbutton () call the display () method of helphandler in the method public void onclick () {help = new helphandler (); help. display (); // display the help document }}
In the code above, the function key class functionbutton acts as the request sender, and the help document processing class helphandler acts as the request receiver. In The onclick () method of the sender functionbutton, the display () of the receiver helphandler is called () method. Obviously, using the above Code will bring the following problems to the system:
(1) because there is direct call of methods between the request sender and the request receiver, the coupling degree is very high,To change the request receiver, you must modify the source code of the sender.If you need to change the request receiver helphandler to javaswhanlder (window processing class), you need to modify the source code of functionbutton, which violates the "open and closed principle ".
(2) The function of the functionbutton class has been fixed during design and implementation. If a new request receiver is added, if the original functionbutton class is not modified, you must add a new class similar to the functionbutton function.As a result, the number of classes in the system increases dramatically.. Because classes such as helphandler and whanlder of the request receiver may not have any relationship, they do not have a common abstraction layer. Therefore, it is difficult to design functionbutton Based on the Dependency inversion principle.
(3)You cannot set a function key as needed.Once the function of a function key class is fixed, the function cannot be changed without modifying the source code, and the system lacks flexibility.
It is easy to know that all these problems are caused by the direct coupling between the functionbutton class of the Request sender and the helphandler, whanlder, and other classes of the Request receiver. How can we reduce the coupling between the request sender and the receiver, so that the same sender can correspond to different receivers? This is something sunny software developers have to consider when designing the "function key settings" module. The command mode is being developed to solve such problems. At this time, if we use the command mode, we can solve the above problems to a certain extent (Note: The command mode cannot solve the problem of increasing the number of classes.). Let's start learning the command mode to see how the command mode decouples the request sender and receiver.
2 command mode Overview
In software development, we often need to send requests (call one or some methods) to some objects, but we do not know who the request receiver is, we do not know which operation is requested. At this time, we especially hope to design software in a loosely coupled way so that the coupling between request senders and request recipients can be eliminated, this makes the call relationship between objects more flexible and allows users to flexibly specify the request recipient and the requested operation. The command mode provides a perfect solution for this type of problem.
The command mode can completely decouple the request sender and receiver. There is no direct reference relationship between the sender and receiver. The object sending the request only needs to know how to send the request, instead of how to complete the request..
The command mode is defined as follows:
Command pattern: encapsulate a request as an object, so that we can parameterize the customer with different requests; queue requests or record request logs, and supports unrecoverable operations. The command mode is an object behavior mode. Its alias is action mode or transaction mode. |
The definition of the command mode is complex. Many terms are mentioned, such as "parameterization of customers with different requests" and "queuing of requests ", the terms "record request logs" and "Support for unrecoverable operations" will be explained in detail later.
The core of the command mode is to introduce the command class, which can reduce the coupling between the sender and the receiver. The request sender only needs to specify a command object, then, call the request recipient's processing method through the command object. Its structure is shown in 3:
Figure 3 command mode structure
The command mode structure includes the following roles:
● Command (Abstract command class): An abstract command class is generally an abstract class or interface, in which methods such as execute () used to execute requests are declared, these methods can call the related operations of the Request receiver.
● Concretecommand (specific command class): a specific command class is a subclass of the abstract command class. It implements the methods declared in the abstract command class, which correspond to specific recipient objects, bind the action of the recipient object. When the execute () method is implemented, the action of the recipient object is called ).
● Invoker: the caller is the request sender. It executes the request through the command object. A caller does not need to determine its receiver during design, so it only has an association with the abstract command class. When running the program, you can inject a specific command object into it, and then call the execute () method of the specific command object to indirectly call related operations of the Request recipient.
● Receiver: the Receiver performs request-related operations and processes the request service.
The essence of the command mode is to encapsulate requests. A request corresponds to a command, which separates the responsibility for issuing commands from the responsibility for executing commands.. Each Command is an operation: the Requesting Party sends a request to execute an operation. The receiving party receives the request and performs the corresponding operation.The command mode allows the requester and the receiver to be independent, so that the requester does not have to know the interfaces of the receiver, do not know how the request is received, whether the operation is executed, when it is executed, and how it is executed.
The key to the command mode is to introduce the abstract command class. The request sender program the abstract command class. Only specific commands that implement the abstract command class are associated with the request receiver.In the simplest abstract command class, only one abstract execute () method is included. Each specific command class stores an ER-type object as an instance variable, therefore, different command classes provide different implementations of the execute () method and call the request processing methods of different receivers.
The typical abstract command code is as follows:
abstract class Command {public abstract void execute();}
For the request sender (caller), the abstract command class will be programmed,You can input a specific command class object at runtime by constructing an injection or setting a value injection.,And call the execute () method of the command object in the business method.The typical code is as follows:
Class invoker {private command; // construct the injection public invoker (command) {This. command = command;} // set the value to public void setcommand (command) {This. command = command;} // business method, used to call the execute () method of the command class public void call () using command.exe cute ();}}
The specific command class inherits the abstract command class, which is associated with the request receiver and implements the execute () method declared in the abstract command class, the receiver's request response method action () is called during implementation. The typical code is as follows:
Class concretecommand extends command {private receiver er extends er; // maintain a reference to the request receiver object public void execute () {receiver er. action (); // call the business processing method of the Request recipient action ()}}
The requester er Class provides the action () method to perform request-related operations. The typical code is as follows:
Class extends er {public void action () {// specific action }}
|
Thoughts Can a request sender correspond to multiple request recipients? How to implement it? |
|
[Author: Liu Wei http://blog.csdn.net/lovelion]