责任链模式

37 阅读4分钟

责任链模式的要点

责任链模式(Chain of Responsibility Pattern)是一种行为设计模式,它允许多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合。其主要要点包括:

  1. 解耦发送者和接收者:请求的发送者不需要知道哪个对象会处理请求。
  2. 动态组合:请求在链上传递,直到找到一个处理请求的对象。
  3. 灵活性:可以通过改变链内的成员或者改变它们的顺序,动态地新增或者删除责任。
  4. 遵循开闭原则:新添加处理者时,无需修改现有代码。

责任链模式的组成部分

  1. 抽象处理者(Handler):定义一个处理请求的接口,并且可选地实现后继链。
  2. 具体处理者(ConcreteHandler):继承处理者接口,实现具体的处理逻辑。
  3. 客户端(Client):向链上的第一个处理者对象提交请求。

具体例子

以下是一个简单的责任链模式示例,展示不同的日志级别处理:

抽象处理者:

public abstract class Logger {
    public static int INFO = 1;
    public static int DEBUG = 2;
    public static int ERROR = 3;
    
    protected int level;
    
    // 责任链中的下一个元素
    protected Logger nextLogger;
    
    public void setNextLogger(Logger nextLogger) {
        this.nextLogger = nextLogger;
    }
    
    public void logMessage(int level, String message) {
        if (this.level <= level) {
            write(message);
        }
        if (nextLogger != null) {
            nextLogger.logMessage(level, message);
        }
    }
    
    protected abstract void write(String message);
}

具体处理者:

public class ConsoleLogger extends Logger {
    public ConsoleLogger(int level) {
        this.level = level;
    }

    @Override
    protected void write(String message) {
        System.out.println("Standard Console::Logger: " + message);
    }
}

public class ErrorLogger extends Logger {
    public ErrorLogger(int level) {
        this.level = level;
    }

    @Override
    protected void write(String message) {
        System.out.println("Error Console::Logger: " + message);
    }
}

public class FileLogger extends Logger {
    public FileLogger(int level) {
        this.level = level;
    }

    @Override
    protected void write(String message) {
        System.out.println("File::Logger: " + message);
    }
}

客户端代码:

public class ChainPatternDemo {
    private static Logger getChainOfLoggers() {
        Logger errorLogger = new ErrorLogger(Logger.ERROR);
        Logger fileLogger = new FileLogger(Logger.DEBUG);
        Logger consoleLogger = new ConsoleLogger(Logger.INFO);

        errorLogger.setNextLogger(fileLogger);
        fileLogger.setNextLogger(consoleLogger);

        return errorLogger;
    }

    public static void main(String[] args) {
        Logger loggerChain = getChainOfLoggers();

        loggerChain.logMessage(Logger.INFO, "This is an information.");
        loggerChain.logMessage(Logger.DEBUG, "This is a debug level information.");
        loggerChain.logMessage(Logger.ERROR, "This is an error information.");
    }
}

在Spring MVC中的实现

在Spring MVC中,拦截器(Interceptor)就是责任链模式的一个实际应用。多个拦截器可以组成一个链,依次对请求进行处理。

定义拦截器接口:

public interface HandlerInterceptor {
    boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
    void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception;
    void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception;
}

具体拦截器类:

public class AuthenticationInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("Authenticating request: " + request.getRequestURI());
        return true; // 继续下一个拦截器或处理器
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 后处理
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 完成处理
    }
}

注册拦截器:

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new AuthenticationInterceptor());
    }
}

在Java类库中的示例

  1. java.util.logging.Logger:Java日志记录API中的Logger类使用了责任链模式来处理日志记录请求。

    • 示例:
      Logger logger = Logger.getLogger(ChainPatternDemo.class.getName());
      logger.setLevel(Level.INFO);
      logger.info("This is an info message");
      logger.severe("This is a severe message");
      
  2. Servlet过滤器:Servlet API中的过滤器链也是责任链模式的一个实现。

    • 示例:
      @WebFilter("/*")
      public class MyFilter implements Filter {
          public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
              System.out.println("Request received");
              chain.doFilter(request, response);
              System.out.println("Response sent");
          }
      }
      

在MyBatis中的示例

MyBatis中的插件机制实现了责任链模式。可以通过自定义插件来拦截和处理MyBatis中的四大对象(Executor、ParameterHandler、ResultSetHandler和StatementHandler)。

自定义插件示例:

@Intercepts({
    @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})
})
public class MyPlugin implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        System.out.println("Intercepted: " + invocation.getMethod().getName());
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
        // Set plugin properties if needed
    }
}

在Angular中的示例

在Angular中,可以使用责任链模式来处理请求拦截器。以下是一个示例:

拦截器定义:

import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const clonedReq = req.clone({ headers: req.headers.set('Authorization', 'Bearer TOKEN') });
    return next.handle(clonedReq);
  }
}

注册拦截器:

import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { AuthInterceptor } from './auth.interceptor';

@NgModule({
  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true },
  ],
})
export class AppModule {}

在React中的示例

在React中,可以使用中间件模式来实现责任链模式。以下是一个示例:

定义中间件:

const loggerMiddleware = store => next => action => {
  console.log('Dispatching:', action);
  let result = next(action);
  console.log('Next State:', store.getState());
  return result;
};

const crashReporterMiddleware = store => next => action => {
  try {
    return next(action);
  } catch (err) {
    console.error('Caught an exception!', err);
    throw err;
  }
};

应用中间件:

import { createStore, applyMiddleware } from 'redux';
import rootReducer from './reducers';

const store = createStore(
  rootReducer,
  applyMiddleware(loggerMiddleware, crashReporterMiddleware)
);