Application scenarios
HTTP Web request processing, after the request will be transcoding, parsing, parameter encapsulation, authentication and a series of processing (responsibility), and after how much processing can be flexibly adjusted so how to do it? How about putting all of your processing in one class? Divided into multiple classes and how to flexibly combine together?
A simple example
Request:
public interface Request {
//do something...
}
Copy the code
ResponsibilityChain class:
public class ResponsibilityChain {
private List<Responsibility> responsibilityList = new ArrayList<>();
private Integer index = 0;
public void process(Request request) {
if (this.index < responsibilityList.size()) {
this.responsibilityList.get(index++).process(request, this); }}/** joins the chain */
public void register(Responsibility responsibility) {
this.responsibilityList.add(responsibility); }}Copy the code
Responsibility interface:
public interface Responsibility {
void process(Request request, ResponsibilityChain chain);
}
Copy the code
Responsibility implementation class:
public class ResponsibilityA implements Responsibility {
@Override
public void process(Request request, ResponsibilityChain chain) {
System.out.println("Transcoding"); chain.process(request); }}Copy the code
public class ResponsibilityB implements Responsibility {
@Override
public void process(Request request, ResponsibilityChain chain) {
System.out.println("Resolution"); chain.process(request); }}Copy the code
public class ResponsibilityC implements Responsibility {
@Override
public void process(Request request, ResponsibilityChain chain) {
System.out.println("Parameter encapsulation"); chain.process(request); }}Copy the code
public class ResponsibilityD implements Responsibility {
@Override
public void process(Request request, ResponsibilityChain chain) {
System.out.println("Authentication"); chain.process(request); }}Copy the code
The test class:
public class Test {
public static void main(String[] args) {
ResponsibilityChain chain = new ResponsibilityChain();
chain.register(new ResponsibilityA());
chain.register(new ResponsibilityB());
chain.register(new ResponsibilityC());
chain.register(new ResponsibilityD());
chain.process(newRequest() { }); }}Copy the code
Class diagram:
Chain of Responsibility model
define
All the handlers, they join the chain, and when one is done, it passes to the next or each recipient contains a reference to the other recipient, and if an object can’t handle the request, it passes the same request to the next recipient
- Abstract out the responsibility interface, the concrete responsibility logic to realize the interface
- Concrete implementations are grouped into chains as required by the process
- User use chain
Typical examples are Filter and Interceptor
intentions
Avoid coupling the request sender with the receiver, make it possible for multiple objects to receive the request, connect the objects into a chain, and pass the request along the chain until an object handles it
Main problem solving
The handler on the responsibility chain is responsible for processing the request, and the client only needs to send the request to the responsibility chain. There is no need for the details of relationship processing and the delivery of the request. The sender and handler of the request are decoupled
When to use
- The system already has a chain of handler objects, which may be given by the composition pattern
- More than one handler object will process a request, and it is not clear in advance which handler object will process a request. Handler objects are dynamically determined
- The system wants to make a request to one of several handler objects, but it is not obvious which handler object will handle the request
- The collection of handler objects that process a request needs to be specified dynamically
The advantages and disadvantages
Advantages:
- Sender and receiver decoupled, low coupling
- Simplifies the object. The object does not need to know the structure of the chain
- Responsibilities can be dynamically added or removed by changing members in the chain or reordering them
- It is convenient to add new request handling classes
Disadvantages:
- There is no guarantee that the request will be received
- System performance will suffer, and it will be inconvenient to debug the code, which may cause circular calls
- Runtime characteristics may not be easily observed, hindering debugging
The class diagram is as follows:Roles involved:
- The Handler role: Defines an interface to handle requests. If necessary, the interface can define a method to set and return references to the next parent. This role is usually implemented by an abstract class or interface
- The ConcreteHandler role: When a ConcreteHandler receives a request, it can either process it or pass it to the next; The concrete handler holds a reference to the next one, so the concrete handler can access the next one if needed
Code example: Handler class:
public abstract class Handler {
protected Handler successor;
/** Call this method to process the request */
public abstract void handlerRequest(a);
/** Method */
public Handler getSuccessor(a) {
return successor;
}
/** Call this method to set the next */
public void setSuccessor(Handler successor) {
this.successor = successor; }}Copy the code
ConcreteHandler:
public class ConcreteHandler1 extends Handler {
@Override
public void handlerRequest(a) {
if(getSuccessor() ! =null) {
System.out.println("Request passed on to the next:" + getSuccessor().getClass().getName());
getSuccessor().handlerRequest();
} else {
System.out.println("Request processed in ConcreteHandler1"); }}}Copy the code
public class ConcreteHandler2 extends Handler {
@Override
public void handlerRequest(a) {
if(getSuccessor() ! =null) {
System.out.println("Request passed on to the next:" + getSuccessor());
getSuccessor().handlerRequest();
} else {
System.out.println("Request processed in ConcreteHandler2"); }}}Copy the code
Client:
public class Client {
static private Handler handler1;
static private Handler handler2;
public static void main(String[] args) {
handler1 = new ConcreteHandler1();
handler2 = newConcreteHandler2(); handler1.setSuccessor(handler2); handler1.handlerRequest(); }}Copy the code
Class diagram:
Beat the drum to pass the story of flowers
Drum passing flowers is a lively and intense drinking game. In the banquet, the guests sit down in turn and one person beats the drum. When the drum starts to beat, the bouquet of flowers will be passed in turn. Here is a small example of the story of beating drums and spreading flowers in a Dream of Red Mansions:Abstract interface Player class:
public abstract class Player {
private Player player;
/** The request to execute the liquor order */
abstract public void handlerRequest(int index);
/** Sets the next bearer */
public void setPlayer(Player player) {
this.player = player;
}
/** passes the flower to the next family, if not, end */
public void next(int index) {
if(player ! =null) {
player.handlerRequest(index);
} else {
System.out.println("The passing of flowers is over."); }}}Copy the code
People who participate in drumming and passing flowers:
public class JiaMu extends Player {
public JiaMu(Player player) {
this.setPlayer(player);
}
@Override
public void handlerRequest(int index) {
if (index == 1) {
System.out.println("Mama Jammu carries out the drinking order.");
} else {
System.out.println("Jammy passes the flower to the next."); next(index); }}}Copy the code
public class JiaShe extends Player {
public JiaShe(Player player) {
this.setPlayer(player);
}
@Override
public void handlerRequest(int index) {
if (index == 2) {
System.out.println("Jia She carries out the drinking order.");
} else {
System.out.println("Jasmine passes flowers to the next."); next(index); }}}Copy the code
public class JiaZheng extends Player {
public JiaZheng(Player player) {
this.setPlayer(player);
}
@Override
public void handlerRequest(int index) {
if (index == 3) {
System.out.println("Jia Zheng executes the drinking order.");
} else {
System.out.println("Jia Zheng passes the flower to the next."); next(index); }}}Copy the code
public class JiaBaoYu extends Player {
public JiaBaoYu(Player player) {
this.setPlayer(player);
}
@Override
public void handlerRequest(int index) {
if (index == 4) {
System.out.println("Jia Baoyu carries out the drinking order.");
} else {
System.out.println("Jia Baoyu passes flowers to the next."); next(index); }}}Copy the code
public class JiaHuan extends Player {
public JiaHuan(Player player) {
this.setPlayer(player);
}
@Override
public void handlerRequest(int index) {
if (index == 5) {
System.out.println("Jia Huan executes the drinking order.");
} else {
System.out.println("Jia Huan passes the flower to the next."); next(index); }}}Copy the code
The drums:
public class DrinkingGame {
static private Player player;
public static void main(String[] args) {
player = new JiaMu(
new JiaShe(
new JiaZheng(
new JiaBaoYu(
new JiaHuan(null)))));
// Set the fourth execution order
player.handlerRequest(4); }}Copy the code
Class diagram: