1. 책임 연쇄(chain of responsibility) 패턴이란?
의도
메시지를 보내는 객체와 이를 받아 처리하는 객체들 간의 결합도를 없애기 위한 패턴.
하나의 요청에 대한 처리가 반드시 한 객체에서만 되지 않고, 여러 객체에게 기회를 주려 한다.
즉, 요청을 보내는 쪽(sender)과 요청을 처리하는 쪽(receiver)의 분리하는 패턴이다.
사용 시기
- 하나 이상의 객체가 요청을 처리해야 하고, 그 요청 처리자 중 어떤 것이 선행자인지 모를 때, 처리자가 자동으로 확정되어야 한다.
- 메시지를 받을 객체를 명시하지 않을 채 여러 객체 중 하나에게 처리를 요청하고 싶을 때
- 요청을 처리할 수 있는 객체 집합이 동적으로 정의되어야 할 때
구조
- Handler : 요청을 처리하는 인터페이스를 정의하고, 후속 처리자와 연결을 구현. 즉, 연결고리에 연결된 다음 객체에서 다시 메시지를 보낸다.
- ConcreteHandler : 책임져야 할 행동이 있다면 스스로 요청일 처리하여 후속 처리자에 접근할 수 있다. 즉, 자신이 처리할 행동이 있으면 처리하고, 그렇지 않으면 후속 처리자에 다시 처리를 요청한다.
- Client : ConcreteHandler 객체에게 필요한 요청을 보낸다.
2. 구현
저번에 ProxyPattern 처럼 class 다이어그램을 그려볼까 했는데
구조 자체가 쉽다(건방지지만...) 하는 관계로 그냥 넘어갈것이다. 데헷.
패키지 구성은 다음과 같다.
RequestHandler.java
//field선언이 필요해 interface 말고 abstract를 사용
public abstract class RequestHandler {
private RequestHandler nextHandler;
public RequestHandler(RequestHandler nextHandler) {
this.nextHandler = nextHandler;
}
public void handle(Request request) {
if (nextHandler != null) {
nextHandler.handle(request);
}
}
}
Request.java
public class Request {
private String body;
public Request(String body) {
this.body = body;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
}
AuthRequestHandler.java
public class AuthRequestHandler extends RequestHandler{
public AuthRequestHandler(RequestHandler nextHandler) {
super(nextHandler);
}
@Override
public void handle(Request request) {
System.out.println("인증 여부");
super.handle(request);
}
}
LogRequestHandler.java
public class LogRequestHandler extends RequestHandler{
public LogRequestHandler(RequestHandler nextHandler) {
super(nextHandler);
}
@Override
public void handle(Request request) {
System.out.println(request.getBody());
super.handle(request);
}
}
PringRequestHandler.java
public class PrintRequestHandler extends RequestHandler{
public PrintRequestHandler(RequestHandler nextHandler) {
super(nextHandler);
}
@Override
public void handle(Request request) {
System.out.println("print");
super.handle(request);
}
}
Client.java
public class Client {
private RequestHandler requestHandler;
public Client(RequestHandler requestHandler) {
this.requestHandler = requestHandler;
}
public void doJob() {
Request request = new Request("한번 테스트를 해보자앙");
requestHandler.handle(request);
}
public static void main(String[] args) {
RequestHandler chain = new AuthRequestHandler(new LogRequestHandler(new PrintRequestHandler(null)));
Client client = new Client(chain);
client.doJob();
}
}
지금처럼 모든 handler를 거쳐가게 할 수도 있고, 중간에 무언가 조건을 줄 수도 있다.
설계자의 마음대로 코드를 조작하면 된다.
근데 무언가 많이 본거같은데...
아하! (혼자 뭐함...?)
Servlet Filter가 이런 구 조이다.
Filter chain에 대해 많이 들어봤을텐데 Filter 와 Interceptor의 차이점이 궁금하면 다음 링크를 참조하면 된다.
그리고 Spring Security도 Filter구조로 많이 작성이 되어 있어서 무언가... chaing을 한다는 개념이 이런 책임 연쇄 패턴이랑 연관이 있을줄 꿈에도 몰랐다.(세상에 마상에)
장점
- 클라이언트 코드를 변경하지 않고 새로운 핸들러를 체인에 추가할 수 있다.
- 각각의 체인은 자신이 해야하는 일만 한다.
- 체인을 다양한 방법으로 구성할 수 있다.
단점
- 디버깅이 조금 어렵다.
이번에는 filter에 대해 책임 연쇄 패턴에 대해 알아보았다.
모든 패턴들이 사실 이미 구현이 되어있는 것이 많고 대부분 잘 사용하면 크게 문제가 없지만
그래도... 근간 원리를 잘 알아야 나은 개발자가 될거라 생각한다.
부족하거나 무언가 더 더했으면 하는 내용이 있으면 피드백 부탁 헤엉
'디자인 패턴(구) > 행위 패턴' 카테고리의 다른 글
메멘토(Memento) 패턴이란? (0) | 2022.04.23 |
---|---|
중재자(Mediator) 패턴이란? (0) | 2022.04.23 |
반복자(Iterator) 패턴이란? (0) | 2022.04.21 |
해석자(Interpreter) 패턴이란? (0) | 2022.04.18 |
커맨트(Command) 패턴이란? (0) | 2022.04.17 |