책임 연쇄 패턴은 객체를 연결리스트와 같은 사슬 방식으로 연결한 후에 요청을 수행하지 못하는 객체인 경우 책임을 다음 객체에 넘기며 책임을 넘기는 형태의 패턴을 말한다. 각각의 체인은 자신이 해야하는 일만 담당하기 때문에 집합 내의 처리 순서를 변경하거나 처리객체를 유연하게 추가 또는 삭제할 수 있다.
@AllArgsConstructor
public class RequestHandler {
private RequestHandler nextHandler;
public void handle(Request request) {
if (nextHandler != null){
nextHandler.handle(request);
}
}
}
요청을 처리할 RequestHandler의 기본 클래스이다. 다른 RequeestHandler를 주입받아 생성되고, handle 메서드를 호출하면 (nextHandler가 null이 아닌경우) 주입받은 핸들러의 handle 메서드를 부른다. 이 클래스 자체가 어떤 의미를 담고있는건 아니고, 얘는 이 클래스를 상속받아서 handle 메서드에 로직을 담아 실행한 후에 다음 체인으로 넘어가게 하기 위한 응용 Handler들의 기본이 되는 클래스가 된다.
@NoArgsConstructor
public class Request { }
public class AuthRequestHandler extends RequestHandler {
public AuthRequestHandler(RequestHandler nextHandler) {
super(nextHandler);
}
@Override
public void handle(Request request) {
//대충 유저 인증하는 코드
System.out.println("AuthRequestHandler.handle");
super.handle(request);
}
}
public class LoggingRequestHandler extends RequestHandler {
public LoggingRequestHandler(RequestHandler nextHandler) {
super(nextHandler);
}
@Override
public void handle(Request request) {
//대충 요청을 로깅하는 코드
System.out.println("LoggingRequestHandler.handle");
super.handle(request);
}
}
public class DoWorkRequestHandler extends RequestHandler{
public DoWorkRequestHandler(RequestHandler nextHandler) {
super(nextHandler);
}
@Override
public void handle(Request request) {
//대충 request를 처리하는 코드
System.out.println("DoWorkRequestHandler.handle");
super.handle(request);
}
}
실제 체인을 실행하는 파트를 맡아줄 클래스들이다. RequestHandler를 상속받아 handle에 뭔가를 수행하는 부분을 추가했다. 실제로 돌아가는 코드를 적진 않았고, 주석으로 대체했다. 각 클래스들은 자신의 책임 내에서 처리할 수 있는 부분을 처리한 다음에 다음 Handler에 Request를 다시 넘긴다. Handler끼리는 서로의 코드에 전혀 간섭하지 않고, 앞에서 무슨 일이 있더라도 자신의 책임을 다하는 것에만 관심을 가지고있다.
public class App {
public static void main(String[] args) {
RequestHandler chain = new AuthRequestHandler(new LoggingRequestHandler(new AuthRequestHandler(null)));
Client client = new Client(chain);
client.doWork();
}
}
@RequiredArgsConstructor
public class Client {
private final RequestHandler requestHandler;
public void doWork() {
Request request = new Request();
requestHandler.handle(request);
}
}
chain을 생성하는 부분을 제외하면 나머지에선 requestHandler의 내용에 간섭하지 않는다. chain의 구조가 바뀌거나, handler가 추가된다고 해도 코드를 크게 변경할 필요가 없다.
책임 연쇄 패턴을 사용하면 객체지향 원칙 중 단일 책임 원칙(Single Responsibility Principle)을 잘 지킬 수 있다.
이 링크로 가면 코드를 볼 수 있다.