This is the 9th day of my participation in Gwen Challenge

Chain of Responsibility model

Chain of responsibility is one of behavioral design patterns. The chain of responsibility mode can be understood as a single linked list structure, where each node is connected to the next child node and each node can be re-connected after disassembly, so the chain structure has flexibility. This structure also applies to design patterns, where each node can be treated as an object, each object has the ability to process business logic and each object is associated with another object. The chain of responsibility pattern is a process where a business request starts at the head of the chain structure and goes down the path, consuming the business logic as soon as an object can handle the business request, depending on the ability of each object to handle the business logic.

implementation

The responsibility chain is implemented as follows: define an abstract ACPU class with the ability to own another abstract ACPU. Inherit ACPU to implement CPU1 and CPU2, and at the same time implement handleRequest method to handle business capabilities.

Assuming a computer with multi-core CPU capability, when a business logic request input is passed from CPU1, if CPU1 is unable to process the request, the handleRequest of the member object CPU is called to continue processing the business logic until a competent CPU can run the business event. Of course, a business logic request does not have to start from CPU1, but can also directly call CPU2 processing method, if you have the ability to determine which CPU has the ability to process the transaction can be directly called.

public abstract class ACPU{
    private ACPU cpu;
    
    public void setCPU(ACPU cpu) {
        this.cpu = cpu;
    }
    public ACPU getCPU(a) {
        return cpu;
    }
    
    public abstract void handleRequest(String request);
}

public CPU1 extends ACPU{
    @override
    public void handleRequest(String request){
        if(request == "2") {if(cpu ! =null)
            cpu.handleRequest(request);
        }else{ run(); }}}public CPU2 extends ACPU{
    @override
    public void handleRequest(String request){
        if(cpu ! =null) {... }else{
            run();
        }
    }
}
CPU1 cpu1 = new CPU1();
CPU2 cpu2 = new CPU2();
cpu1.setCPU(cpu2);
cpu1.handleRequest("2");
cpu1.handleRequest("1");
cpu2.handleRequest("1");Copy the code

The instance

The interceptor in the OkHttp open source library uses the chain of responsibility model.

Add interceptors of various types to the interceptors collection, which is eventually passed to the RealInterceptorChain.

Response getResponseWithInterceptorChain(a) throws IOException {
 
    List<Interceptor> interceptors = new ArrayList<>();
    interceptors.addAll(client.interceptors());
    interceptors.add(retryAndFollowUpInterceptor);
    interceptors.add(new BridgeInterceptor(client.cookieJar()));
    interceptors.add(new CacheInterceptor(client.internalCache()));
    interceptors.add(new ConnectInterceptor(client));
    if(! forWebSocket) { interceptors.addAll(client.networkInterceptors()); } interceptors.add(new CallServerInterceptor(forWebSocket));
  
    Interceptor.Chain chain = new RealInterceptorChain(interceptors, null.null.null.0,
        originalRequest, this, eventListener, client.connectTimeoutMillis(),
        client.readTimeoutMillis(), client.writeTimeoutMillis());

    return chain.proceed(originalRequest);
}

Copy the code

RealInterceptorChain is an interceptor manager that iterates through interceptors to create RealInterceptorChain objects to recursively process requests until one interceptor is able to process the request.

public final class RealInterceptorChain implements Interceptor.Chain {...public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec, RealConnection connection) throws IOException {
        if (index >= interceptors.size()) throw newAssertionError(); calls++; .// Call the next interceptor in the chain.
        RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec, 
        connection, index + 1, request, call, eventListener, connectTimeout, readTimeout, writeTimeout); Interceptor interceptor = interceptors.get(index); Response response = interceptor.intercept(next); .returnresponse; }}//Interceptor Interceptor interface
public interface Interceptor {
  /** * intercepts the Chain and triggers the next interceptor call *@paramChain Object to be processed *@return
   * @throws IOException
   */
  Response intercept(Chain chain) throws IOException;

  interface Chain {
    // Return the request
    Request request(a);
    // Process the request
    Response proceed(Request request) throws IOException; . }}Copy the code

conclusion

The chain of responsibility mode seems to be an optimization of if-else form. The advantage is that it decouples the relationship between requestor and handler from the perspective of structure, thus improving flexibility. The disadvantages are also obvious as the number of responsibility chain handlers increases and the depth of chain calls increases, traversing the entire link becomes one of the reasons for the performance impact, especially with the use of recursive calling functions.

reference

  • OkHttp’s chain of responsibility pattern