Chain of responsibility Definition
Chain of responsibility (CoR) is to use a series of classes (classes) to try to process a request. These classes are loosely coupled and the only thing in common is to pass requests between them. that is to say, when a request comes, Class A first processes it. If it is not processed, it is passed to Class B for processing. If it is not processed, it is passed to Class C for processing, it is passed down like a chain.
How to use it?
Although how to use cor in this section, it also demonstrates what cor is.
There is a handler interface:
Public interface handler {
Public void handlerequest ();
}
This is an example of processing a request. If there are multiple requests, such as the request help request printing or request formatting:
The first solution is to add multiple requests to the interface:
Public interface handler {
Public void handlehelp ();
Public void handleprint ();
Public void handleformat ();
}
It is a piece of implementation interface handler code:
Public class concretehandler implements handler {
Private handler successor;
Public concretehandler (handler successor ){
This. Successor = successor;
}
Public void handlehelp (){
// Code for processing the help request
...
}
Public void handleprint (){
// If print is used for forwarding, print
Successor. handleprint ();
}
Public void handleformat (){
// If format is used for format conversion
Successor. handleformat ();
}
}
There are three such specific implementation classes: processing Help and processing print format, which is probably our most common programming idea.
Although the idea is simple and clear, there is a scaling problem. If we need to add another request type, we need to modify the interface and each of its implementations.
Solution 2: convert each request into an interface, so we have the following code:
Public interface helphandler {
Public void handlehelp ();
}
Public interface printhandler {
Public void handleprint ();
}
Public interface formathandler {
Public void handleformat ();
}
Public class concretehandler
Implements helphandler, printhandler, formathandlet {
Private helphandler helpsuccessor;
Private printhandler printsuccessor;
Private formathandler formatsuccessor;
Public concretehandler (helphandler helpsuccessor, printhandler printsuccessor, formathandler formatsuccessor)
{
This. helpsuccessor = helpsuccessor;
This. printsuccessor = printsuccessor;
This. formatsuccessor = formatsuccessor;
}
Public void handlehelp (){
.......
}
Public void handleprint () {This. printsuccessor = printsuccessor ;}
Public void handleformat () {This. formatsuccessor = formatsuccessor ;}
}
When a new request is added, this method only saves the number of changes to the interface, and the concretehandler needs to be modified. And the code is obviously not simple and beautiful.
Solution 3: use only one parameterized method in the handler interface:
Public interface handler {
Public void handlerequest (string request );
}
The handler implementation code is as follows:
Public class concretehandler implements handler {
Private handler successor;
Public concretehandler (handler successor ){
This. Successor = successor;
}
Public void handlerequest (string request ){
If (request. Equals ("help ")){
// Here is the specific code for processing Help
} Else
// Pass to the next
Successor. Handle (request );
}
}
}
Assume that the request is of the string type. What if not? Of course, we can create a special request class.
Solution: the handler code of the interface is as follows:
Public interface handler {
Public void handlerequest (request );
}
Request class definition:
Public class request {
Private string type;
Public request (string type) {This. type = type ;}
Public String GetType () {return type ;}
Public void execute (){
// Actual request behavior code
}
}
The handler implementation code is as follows:
Public class concretehandler implements handler {
Private handler successor;
Public concretehandler (handler successor ){
This. Successor = successor;
}
Public void handlerequest (request ){
If (request instanceof helprequest ){
// Here is the specific code for processing Help
} Else if (request instanceof printrequst ){
Request.exe cute ();
} Else
// Pass to the next
Successor. Handle (request );
}
}
}
This solution is Cor, which has classes with corresponding responsibilities on a chain.Chain of responsibility.
Advantages of Cor:
It is impossible to predict the type of requests from the outside world (client). If each class encounters a request that cannot be processed by the client, it only needs to give up.
The disadvantage is that the efficiency is low, because the completion of a request may be completed only after the traversal ends. Of course, the tree concept can also be used for optimization. In Java awt1.0, Cor is used to handle mouse buttons. After java.1.1, observer is used to replace cor.
Poor scalability, because in Cor, there must be a unified interface handler. The limitations are here.
Differences from command mode:
In command mode, you need to negotiate the call relationship between the client and the server in advance, for example, 1 indicates start 2 indicates move, and so on. These are all encapsulated in the request and then decomposed at the server end.
The CoR mode does not require such prior conventions. The server can use the CoR mode to guess client requests and perform one-by-one guessing test.