责任链模式的要点
责任链模式(Chain of Responsibility Pattern)是一种行为设计模式,它允许多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合。其主要要点包括:
- 解耦发送者和接收者:请求的发送者不需要知道哪个对象会处理请求。
- 动态组合:请求在链上传递,直到找到一个处理请求的对象。
- 灵活性:可以通过改变链内的成员或者改变它们的顺序,动态地新增或者删除责任。
- 遵循开闭原则:新添加处理者时,无需修改现有代码。
责任链模式的组成部分
- 抽象处理者(Handler):定义一个处理请求的接口,并且可选地实现后继链。
- 具体处理者(ConcreteHandler):继承处理者接口,实现具体的处理逻辑。
- 客户端(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类库中的示例
-
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");
- 示例:
-
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)
);