Chain Of Responsibility Pattern

책임 연쇄 패턴 특정 요청이 들어올 경우, 해당 요청을 연결리스트와 같은 사슬 방식으로 객체끼리 연결하여 요청을 수행하지 못할 경우, 다음 객체에 떠넘기는 형태의 패턴.

책임 연쇄 패턴 특징

SRP : 단일 책임 원칙, 하나의 객체에서는 하나의 책임만 담당한다.
OCP : 개방 폐쇄 원칙, 기존 코드를 해하지 않고 확장할 수 있다.
요청 처리 순서를 제어할 수 있다.
→ 결합을 느슨하게 하기 위해 고안됨. 프로그래밍에서 가장 좋은 사례.

대표적인 예

Java try~catch
스프링 시큐리티
Clean architecture
window dom 구조

UML 1

1.
Handler : 모든 구체적인 핸들러에 공통적인 인터페이스를 선언합니다. 일반적으로 요청을 처리하기 위한 단일 메서드만 포함하지만 때로는 체인에서 다음 핸들러를 설정하기 위한 다른 메서드가 있을 수도 있습니다.
2.
BaseHandler : 는 모든 핸들러 클래스에 공통 코드를 넣을 수 있는 기본 클래스입니다.
일반적으로 이 클래스는 다음 핸들러에 대한 참조를 저장하기 위한 필드를 정의합니다. 클라이언트는 핸들러를 이전 핸들러의 생성자 또는 설정자에 전달하여 체인을 구축할 수 있습니다. 클래스는 기본 처리 동작을 구현할 수도 있습니다. 즉, 존재 여부를 확인한 후 다음 처리기로 실행을 전달할 수 있습니다.
3.
생성자 :  에는 요청을 처리하기 위한 실제 코드가 포함되어 있습니다. 요청을 받으면 각 핸들러는 요청을 처리할지 여부와 함께 체인을 따라 전달할지 여부를 결정해야 합니다.
핸들러는 일반적으로 자체 포함되고 변경할 수 없으며 생성자를 통해 필요한 모든 데이터를 한 번만 수락합니다.
4.
클라이언트 는 응용 프로그램의 논리에 따라 체인을 한 번만 구성하거나 동적으로 구성할 수 있습니다. 요청은 체인의 모든 핸들러로 보낼 수 있습니다. 첫 번째 핸들러일 필요는 없습니다.

UML 2

요청을 보내는 쪽(sender)과 요청을 처리하는(receiver) 쪽을 분리하는 패턴.
-> 핸들러 체인을 사용해서 요청을 처리한다.

예제

public abstract class Handler { public String name; private Handler next; public Handler(String name) { this.name = name; } public void setNext(Handler next) { this.next = next; } public void handleRequest(int number) { if (canHandle(number)) { print(number); // chain이 연결되어 있으면 다음 처리 객체에 문제 전달 (oddHandler -> evenHandler 순으로 처리) } else if (next != null) { next.handleRequest(number); } else { System.out.println("처리할 수 있는 객체 없음"); } } public void print(int number) { System.out.println(number + ":" + name + "로 처리"); } public abstract boolean canHandle(int number); }
Java
복사
public class OddHandler extends Handler { public OddHandler(String name) { super(name); } public boolean canHandle(int number) { return number % 2 != 0; } }
Java
복사
public class EvenHandler extends Handler { public EvenHandler(String name) { super(name); } public boolean canHandle(int number) { return number % 2 == 0; } }
Java
복사
// main Handler oddHandler = new OddHandler("홀수"); Handler evenHandler = new EvenHandler("짝수"); // chain 연결 oddHandler -> evenHandler oddHandler.setNext(evenHandler); for (int i = 1; i <= 10; i++) { oddHandler.handleRequest(i); }
Java
복사

단점

디버깅이 어렵다. (특정 체인을 찾아야하며, 시간 체크가 어렵다.)
객체 폭발이 일어난다.요청을 보내는 쪽(sender)과 요청을 처리하는(receiver) 쪽을 분리하는 패턴.
-> 핸들러 체인을 사용해서 요청을 처리한다.