← Назад к вопросам
Для чего нужен паттерн цепочка ответственности?
2.0 Middle🔥 81 комментариев
#SOLID и паттерны проектирования
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
# Паттерн Цепочка ответственности (Chain of Responsibility)
Определение
Цепочка ответственности (Chain of Responsibility) — поведенческий паттерн проектирования, который позволяет передавать запросы по цепи обработчиков, где каждый обработчик решает, обработать запрос или передать его следующему в цепи.
Основное назначение
1. Абстракция обработчиков
Паттерн создаёт цепь независимых обработчиков:
// Абстрактный обработчик
public abstract class Handler {
protected Handler nextHandler;
public void setNext(Handler handler) {
this.nextHandler = handler;
}
// Шаблонный метод
public void handle(Request request) {
if (canHandle(request)) {
process(request);
} else if (nextHandler != null) {
nextHandler.handle(request);
}
}
protected abstract boolean canHandle(Request request);
protected abstract void process(Request request);
}
2. Конкретные обработчики
Каждый обработчик отвечает за свою задачу:
public class AuthenticationHandler extends Handler {
@Override
protected boolean canHandle(Request request) {
return request.type() == RequestType.AUTHENTICATION;
}
@Override
protected void process(Request request) {
System.out.println("Проверка аутентификации: " + request.getUser());
}
}
public class AuthorizationHandler extends Handler {
@Override
protected boolean canHandle(Request request) {
return request.type() == RequestType.AUTHORIZATION;
}
@Override
protected void process(Request request) {
System.out.println("Проверка прав доступа: " + request.getPermission());
}
}
public class LoggingHandler extends Handler {
@Override
protected boolean canHandle(Request request) {
return true; // Обрабатываем всегда
}
@Override
protected void process(Request request) {
System.out.println("Логирование запроса: " + request.getId());
}
}
3. Построение цепи
Обработчики объединяются в цепь:
public class RequestProcessor {
public static void main(String[] args) {
// Создание обработчиков
Handler authHandler = new AuthenticationHandler();
Handler authzHandler = new AuthorizationHandler();
Handler logHandler = new LoggingHandler();
// Построение цепи
authHandler.setNext(authzHandler);
authzHandler.setNext(logHandler);
// Запрос обрабатывается по цепи
Request request = new Request(RequestType.AUTHENTICATION, "user123");
authHandler.handle(request);
// Результат: AuthenticationHandler обработает, затем передаст AuthorizationHandler
}
}
4. Реальный пример: Обработка запросов в веб-приложении
public class HttpRequest {
private String method;
private String path;
private Map<String, String> headers;
private String body;
// getters...
}
// Обработчик CORS
public class CorsHandler extends RequestHandler {
@Override
public void handle(HttpRequest request) {
if (request.getHeaders().containsKey("Origin")) {
System.out.println("CORS проверка: " + request.getHeaders().get("Origin"));
// Добавляем CORS заголовки в ответ
}
if (nextHandler != null) {
nextHandler.handle(request);
}
}
}
// Обработчик аутентификации
public class AuthenticationHandler extends RequestHandler {
@Override
public void handle(HttpRequest request) {
String token = request.getHeaders().get("Authorization");
if (token == null || !isValidToken(token)) {
System.out.println("Ошибка аутентификации!");
return; // Цепь прерывается
}
System.out.println("Токен валиден: " + token);
if (nextHandler != null) {
nextHandler.handle(request);
}
}
private boolean isValidToken(String token) {
return token.startsWith("Bearer ");
}
}
// Обработчик бизнес-логики
public class BusinessLogicHandler extends RequestHandler {
@Override
public void handle(HttpRequest request) {
System.out.println("Обработка запроса: " + request.getMethod() + " " + request.getPath());
if (nextHandler != null) {
nextHandler.handle(request);
}
}
}
// Использование
public class Server {
public void initChain() {
RequestHandler cors = new CorsHandler();
RequestHandler auth = new AuthenticationHandler();
RequestHandler business = new BusinessLogicHandler();
cors.setNext(auth);
auth.setNext(business);
HttpRequest request = new HttpRequest("GET", "/api/users");
request.addHeader("Origin", "http://localhost:3000");
request.addHeader("Authorization", "Bearer eyJhbGc...");
cors.handle(request);
}
}
5. Применение в фреймворках
Spring Security (фильтры):
// Spring создаёт цепь фильтров автоматически
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.cors() // CORS фильтр
.and()
.csrf() // CSRF защита
.and()
.authorizeHttpRequests()
.requestMatchers("/api/public/**").permitAll()
.anyRequest().authenticated()
.and()
.httpBasic(); // Basic Auth
return http.build();
}
}
// Внутри Spring автоматически создаёт цепь фильтров
AOP (Aspect-Oriented Programming) — альтернатива:
@Aspect
@Component
public class LoggingAspect {
@Before("@annotation(com.example.Loggable)")
public void logBefore(JoinPoint jp) {
System.out.println("До выполнения: " + jp.getSignature());
}
@After("@annotation(com.example.Loggable)")
public void logAfter(JoinPoint jp) {
System.out.println("После выполнения: " + jp.getSignature());
}
}
6. Преимущества и недостатки
Преимущества:
- Слабая связанность между обработчиками
- Легко добавлять новые обработчики
- Порядок обработки гибкий
- Разделение ответственности
Недостатки:
- Сложность отладки (откуда взялся результат?)
- Гарантии обработки нет (может остаться необработанным)
- Производительность (много объектов в цепи)
7. Где используется
- Веб фреймворки: Spring Security, middleware в Express.js
- Логирование: Logger в Java (обработчик эскалирует ошибку выше)
- GUI компоненты: обработка событий (mouseClick передаётся родителю)
- REST APIs: middleware для аутентификации, валидации, трансформации
- Платёжные системы: обработка платежей через несколько уровней проверок
Выводы
Цепочка ответственности — это мощный паттерн для:
- Разделения обработки запроса на независимые этапы
- Создания гибких и расширяемых систем обработки
- Реализации middleware и фильтров в веб-приложениях
- Изоляции ответственности каждого обработчика
Визуально цепь представляет собой последовательность объектов, каждый из которых имеет шанс обработать запрос или передать его следующему.