1. 책임 연쇄 패턴(Chain of Responsibility pattern)
책임 연쇄 패턴은 핸들러들의 체인(사슬)을 따라 요청을 전달할 수 있게 해주는 행동 디자인 패턴이다. 각 핸들러는 요청을 받으면 요청을 처리할지 또는 체인의 다음 핸들러로 전달할지 결정한다.
책임 연쇄 패턴을 사용하면 SRP 를 지킬 수 있다. SRP 는 객체는 단 하나의 책임을 가져야 한다는 원칙이다. 즉, 변경되어야 할 이유 또한 한가지여야 한다는 의미이다. 책임 연쇄 패턴을 사용하면 각 핸들러에게 책임을 맡기고 핸들러 책임 외에는 다른 핸들러에게 위임하기 때문에 SRP 를 지킬 수 있다.
책임 연쇄 패턴은 요청을 보내는 주체와 요청을 처리하는 주체를 분리하는 패턴으로 요청을 보내는 주체가 요청을 처리하는 핸들러가 구체적인 타입에 상관없이 디커플링 된 상태에서 처리 가능하도록 해주는 패턴이다.
sample code : Client
class Main {
public static void main(String[] args) {
RequestHandler chainingRequestHandler =
new RequestHandler(
new RequestUuidHandler(
new RequestLoggingHandler(null)));
final Client client = new Client(chainingRequestHandler);
client.doWork("hello request");
}
}
class Client {
private final RequestHandler requestHandler;
public Client(final RequestHandler requestHandler) {
this.requestHandler = requestHandler;
}
void doWork(final String request) {
requestHandler.handle(request);
}
}
sample code : RequestHandler Chaining
// RequestHandler
public class RequestHandler {
private RequestHandler nextHandler;
public RequestHandler(RequestHandler nextHandler) {
this.nextHandler = nextHandler;
}
public void handle(String request) {
nextHandler.handle(request);
}
}
// RequestLoggingHandler
public class RequestLoggingHandler extends RequestHandler {
private RequestHandler nextHandler;
public RequestLoggingHandler(RequestHandler nextHandler) {
super(nextHandler);
}
@Override
public void handle(final String request) {
System.out.println("2. request logging start ======================");
System.out.println("logging request : " + request);
System.out.println("2. request logging end ======================");
if (nextHandler == null) {
return;
}
super.handle(request);
}
}
// RequestUuidHandler
public class RequestUuidHandler extends RequestHandler {
private RequestHandler nextHandler;
public RequestUuidHandler(RequestHandler nextHandler) {
super(nextHandler);
}
@Override
public void handle(final String request) {
System.out.println("1. request uuid start ======================");
UUID uuid = UUID.randomUUID();
System.out.println("request uuid : " + uuid.toString());
super.handle(request);
System.out.println("1. request uuid end ======================");
}
}
Result

2. 책임 연쇄 패턴의 장단점
책임 연쇄 패턴의 장점은 SRP 를 지키면서 기능을 추가할 수 있다. 새로운 기능을 추가하고 싶은 경우 새로운 핸들러를 등록하고 순서를 결정하면 클라이언트 코드 변경없이 기능을 추가할 수 있다.
그리고 요청의 처리 순서를 제어하고 특정 요청에 한해서만 실행 가능하도록 설정이 가능하다. 하지만 특정 요청이 처리되지 않을 수 있기 때문에 주의해야 한다.
단점은 디버깅이 번거롭다. filter chaining 을 통한 핸들러가 증가하면 원하는 핸들러를 찾기 위해 체이닝 되어 있는 핸들러를 탐색해야 하기 때문에 번거롭다.
3. 책임 연쇄 패턴 예시
스프링 시큐리티에서 filter chain 를 기반해서 인증, 인가 기능을 제공한다.
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
// do something before the rest of the application
chain.doFilter(request, response); // invoke the rest of the application
// do something after the rest of the application
}
Reference
- spring security architecture reference : https://docs.spring.io/spring-security/reference/servlet/architecture.html
- [refactoring.guru] 책임 연쇄 패턴 : https://refactoring.guru/ko/design-patterns/chain-of-responsibility
- [inflearn] 코딩으로 학습하는 GoF의 디자인 패턴
'java > summary' 카테고리의 다른 글
퍼사드 패턴(Facade Pattern) (0) | 2024.07.08 |
---|---|
커맨드 패턴(command pattern) (0) | 2024.07.08 |
싱글톤 패턴(singleton pattern) (0) | 2024.07.03 |
정밀 연산에는 BigDecimal 을 사용하자 (0) | 2024.04.24 |
Garbage Collector simple summary (0) | 2024.03.04 |
1. 책임 연쇄 패턴(Chain of Responsibility pattern)
책임 연쇄 패턴은 핸들러들의 체인(사슬)을 따라 요청을 전달할 수 있게 해주는 행동 디자인 패턴이다. 각 핸들러는 요청을 받으면 요청을 처리할지 또는 체인의 다음 핸들러로 전달할지 결정한다.
책임 연쇄 패턴을 사용하면 SRP 를 지킬 수 있다. SRP 는 객체는 단 하나의 책임을 가져야 한다는 원칙이다. 즉, 변경되어야 할 이유 또한 한가지여야 한다는 의미이다. 책임 연쇄 패턴을 사용하면 각 핸들러에게 책임을 맡기고 핸들러 책임 외에는 다른 핸들러에게 위임하기 때문에 SRP 를 지킬 수 있다.
책임 연쇄 패턴은 요청을 보내는 주체와 요청을 처리하는 주체를 분리하는 패턴으로 요청을 보내는 주체가 요청을 처리하는 핸들러가 구체적인 타입에 상관없이 디커플링 된 상태에서 처리 가능하도록 해주는 패턴이다.
sample code : Client
class Main {
public static void main(String[] args) {
RequestHandler chainingRequestHandler =
new RequestHandler(
new RequestUuidHandler(
new RequestLoggingHandler(null)));
final Client client = new Client(chainingRequestHandler);
client.doWork("hello request");
}
}
class Client {
private final RequestHandler requestHandler;
public Client(final RequestHandler requestHandler) {
this.requestHandler = requestHandler;
}
void doWork(final String request) {
requestHandler.handle(request);
}
}
sample code : RequestHandler Chaining
// RequestHandler
public class RequestHandler {
private RequestHandler nextHandler;
public RequestHandler(RequestHandler nextHandler) {
this.nextHandler = nextHandler;
}
public void handle(String request) {
nextHandler.handle(request);
}
}
// RequestLoggingHandler
public class RequestLoggingHandler extends RequestHandler {
private RequestHandler nextHandler;
public RequestLoggingHandler(RequestHandler nextHandler) {
super(nextHandler);
}
@Override
public void handle(final String request) {
System.out.println("2. request logging start ======================");
System.out.println("logging request : " + request);
System.out.println("2. request logging end ======================");
if (nextHandler == null) {
return;
}
super.handle(request);
}
}
// RequestUuidHandler
public class RequestUuidHandler extends RequestHandler {
private RequestHandler nextHandler;
public RequestUuidHandler(RequestHandler nextHandler) {
super(nextHandler);
}
@Override
public void handle(final String request) {
System.out.println("1. request uuid start ======================");
UUID uuid = UUID.randomUUID();
System.out.println("request uuid : " + uuid.toString());
super.handle(request);
System.out.println("1. request uuid end ======================");
}
}
Result

2. 책임 연쇄 패턴의 장단점
책임 연쇄 패턴의 장점은 SRP 를 지키면서 기능을 추가할 수 있다. 새로운 기능을 추가하고 싶은 경우 새로운 핸들러를 등록하고 순서를 결정하면 클라이언트 코드 변경없이 기능을 추가할 수 있다.
그리고 요청의 처리 순서를 제어하고 특정 요청에 한해서만 실행 가능하도록 설정이 가능하다. 하지만 특정 요청이 처리되지 않을 수 있기 때문에 주의해야 한다.
단점은 디버깅이 번거롭다. filter chaining 을 통한 핸들러가 증가하면 원하는 핸들러를 찾기 위해 체이닝 되어 있는 핸들러를 탐색해야 하기 때문에 번거롭다.
3. 책임 연쇄 패턴 예시
스프링 시큐리티에서 filter chain 를 기반해서 인증, 인가 기능을 제공한다.
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
// do something before the rest of the application
chain.doFilter(request, response); // invoke the rest of the application
// do something after the rest of the application
}
Reference
- spring security architecture reference : https://docs.spring.io/spring-security/reference/servlet/architecture.html
- [refactoring.guru] 책임 연쇄 패턴 : https://refactoring.guru/ko/design-patterns/chain-of-responsibility
- [inflearn] 코딩으로 학습하는 GoF의 디자인 패턴
'java > summary' 카테고리의 다른 글
퍼사드 패턴(Facade Pattern) (0) | 2024.07.08 |
---|---|
커맨드 패턴(command pattern) (0) | 2024.07.08 |
싱글톤 패턴(singleton pattern) (0) | 2024.07.03 |
정밀 연산에는 BigDecimal 을 사용하자 (0) | 2024.04.24 |
Garbage Collector simple summary (0) | 2024.03.04 |