The command mode name is strange, especially when translated into Chinese. In Chinese, "commands" generally refer to commands issued by superiors to lower-level users. But how can commands be issued in programming? This is the first thing I feel after seeing this name. I don't know if anyone else feels the same as me at first ~. In fact, why is it called the command mode? This is justified. My personal understanding is: in the past when desktop applications were popular, many applications were based on windows, so naturally there were a lot of menus, tool bars, and so on. In these menus, each specific operation (such as opening/closing a file, copying and pasting) corresponds to a specific instruction, and the command mode is related to the preceding operation instruction, therefore, it was later named "command mode ". In fact, I personally think that the "command mode" may be easier to understand.
The command mode mainly solves the problem of coupling between requests and request processing programs. In this case, the application scope of the command mode is very wide. For example, in the previously mentioned Window menu, each specific operation corresponds to a request, and each request corresponds to a unique processing program. In web development, a request is sent to the Web server every time a Web page is submitted. on the server side, a corresponding processing program is provided to process the request. The command mode is applicable to the request-processing model. Let's take a look at how the traditional programming method processes such requests-the processing mode (using pseudocode snippets as an example ):
Publicprocessrequest (request ){
If (request = "Delete the current user "){
Deletethe corresponding record in dB;
} Elseif (request = "Inquiry all users "){
Inquiryall the users in dB;
} Elseif (request = "Modify the authority of the current user "){
Modifythe authority of user;
} Elseif .....
}
In this example, we can see that the program uses a large number of IF and else if conditions to distinguish different requests and process the corresponding requests, all requests are processed in one module. If one day we need to add a new type of request processing, such as adding a new blog function to the user, then we need to add new judgments in the existing program and perform corresponding processing. The following program determines:
Public processrequest (request ){
If (request = "Delete the current user "){
Deletethe corresponding record in dB;
} Elseif (request = "Inquiry all users "){
Inquiryall the users in dB;
} Elseif (request = "Modify the authority of the current user "){
Modifythe authority of user;
} Else if (request = "Add a new Bolg forthe current user "){
Adda new Bolg for the user;
} Elseif .....
}
Similarly, when new requirements emerge, we need to modify the code that has run stably to meet new processing requirements, so that new problems may be introduced, because we do not know whether the new modification will affect the previous code, and it is possible that during our modification, we accidentally changed the original module that should not be modified, however, this test case was not included in subsequent tests. Unfortunately, it may occur after the system is released.
According to the open-close principle in one of the OO principles, the program design should be closed to the modifications and open to the added processing components. For details, the program design should meet the following requirements: when new requirements need to be processed, the original processing program should not be modified, but the new requirements should be handled by adding a new processing module. However, according to the traditional design method, when there is a new requirement, the original program will be modified, which violates the OO principle. Is there any way to do this: simply adding new modules without modifying the original modules can handle new requirements? The answer is yes.
Next I will explain through my own understanding how to improve the original design methods step by step to meet the OO open and closed principles. First, we need to restore the request-processing scenario in reality:
The application on the server side is always running. Wait for the client request to arrive. When the request arrives, the matching module selects a matching processing component based on the specific request type to process the request. In this process, the matching module maintains the correspondence between the request and its processing components, for example (request1-> handler1, request2-> handler2), that is, the matching module must know in advance the request corresponding to the processing component, and the corresponding relationship is almost hardcoded in the program logic. When there is a new requirement to increase the request type, we need to add new processing components and modify the matching module. In this way, the relationship between the "matching module" and "processing component" is directly labeled, so that the "matching module" must be changed every time a new request type is added.
Is there a way to properly Add a request type without modifying the "matching module? The answer should be yes.
Below we try to use the preliminary solution:
(1) At the processing component layer: abstract a unified interface method for processing requests, so that all processing components can implement the same interface (such as handle ()), then, the "matching module" calls different processing components using the same interface method.
(2) At the matching Module layer: the corresponding function extension is also required to create a ing mechanism so that each request type corresponds to a unique processing component. When the request arrives, this module automatically searches for the prime ing table and finds the corresponding processing component, and then calls the interface method of the processing component.
After the above two steps, when a new request type is added, we do not need to modify the "matching module", but meet the open and closed principles.
Can the above solutions really stand up to scrutiny? In large applications, different types of services (such as data query, Update service, order service, and computing service) are provided in the backend. These services involve different fields, some of these services may be written by ourselves, and some use services from other providers (service interfaces are certain and cannot be changed ). Obviously, the interfaces of different services (processing components) are different. Therefore, it is impossible to unify the interfaces of all processing components.
Therefore, the above scheme does not apply to all situations, especially when the processing component functions are different and provided by different providers.
Let's dive into the above solutions:
1. Insert a new component "Proxy component" between the "matching module" and "processing component" (not the proxy mode ). Each "processing component" requires a corresponding proxy. Its main functions include:
(1) The conversion request parameter makes it suitable for the interface parameter type of the Service Interface (processing component.
(2) call the real processing component service.
(3) provide unified interface methods to the "matching module" for calling.
Because the proxy layer is designed and implemented by ourselves, we can make all proxy objects have a unified interface method (by implementing the same interface ), then, the real service is called in the proxy object.
Through the above in-depth design, we can meet the principle of opening and closing. Because every time a new request type is added, we only need
(1) create a proxy class implementation based on the new processing component (service.
(2) Add a new request type and the corresponding proxy classes above to the ing table.
The above is the command mode in my understanding. As for the class diagram, the online scheme will not be attached.