-
Chain of Responsibility Pattern(책임 연쇄 패턴)STUDY/디자인패턴 2025. 1. 20. 22:41
책임 연쇄 패턴이란?
핸들러들의 체인을 따라 요청을 전달할 수 있게 해주는 행동 디자인 패턴으로, 각 핸들러는 요청을 받으면 요청을 처리할지 아니면 체인의 다음 핸들러로 전달할지 결정한다.
즉, 클라이언트의 요청에 대한 처리를 하나의 객체가 하는 것이 아닌, 여러 개의 객체들로 나누고 이들을 사슬처럼 연결해 집합 안에서 연쇄적으로 처리하는 행동 패턴이라 하고, 이러한 요청 처리 객체들을 핸들러라고 한다.
구조
- Handler
요청을 수신하고 처리 객체들의 집합을 정의하는 인터페이스로, 일반적으로 요청을 처리하기 위한 단일 메서드만 포함되지만 때로는 체인의 다음 핸들러를 세팅하기 위한 메서드가 존재할 수 있다.
- BaseHandler
선택적 클래스로, 모든 핸들러 클래스들에 공통적인 상용구 코드를 넣을 수 있다. 일반적으로 다음 핸들러에 대한 참조 필드를 가지고 있다. 클라이언트들은 핸들러를 이전 핸들러의 생성자 또는 setter에 전달하여 체인을 구축할 수 있다. 베이스핸들러는 디폴트 핸들러 행동을 구현할 수도 있고, 다음 핸들러의 존재 여부를 확인한 후 다음 핸들러로 요청을 넘길 수 있다.
- ConcreteHandler
요청을 처리하는 실제 처리 객체로, 각 핸들러는 요청을 받으면 요청을 처리할지와 다음 핸들러로 전달할지 결정한다. 핸들러들은 일반적으로 불변이며, 생성자를 통해 필요한 모든 데이터를 한 번만 받는다.
- Client
앱의 논리에 따라 체인들을 한 번만 구성하거나 동적으로 구성할 수 있다. 요청은 체인의 모든 핸들러에 보낼 수 있으며, 꼭 첫번째 핸들러일 필요는 없다.
예시
Handler
public interface ComponentWithContextualHelp { void showHelp(); }
BaseHandler
public class Component implements ComponentWithContextualHelp { protected String tooltipText; protected Component next; public void setTooltipText(String tooltipText) { this.tooltipText = tooltipText; } public Component setNext(Component container) { this.next = container; return container; } @Override public void showHelp() { if (tooltipText != null) { System.out.println("Tooltip: " + tooltipText); } else if (next != null) { next.showHelp(); } } }
ConcreteHandler
public class Button extends Component { private final String label; public Button(String label) { this.label = label; } } public class Panel extends Component { private String modalHelpText; public void setModalHelpText(String modalHelpText) { this.modalHelpText = modalHelpText; } @Override public void showHelp() { if (modalHelpText != null) { System.out.println("Modal Help: " + modalHelpText); } else { super.showHelp(); } } } public class Dialog extends Component { private String pageURL; public void setPageURL(String pageURL) { this.pageURL = pageURL; } @Override public void showHelp() { if (pageURL != null) { System.out.println("Opening Help Page: " + pageURL); } else { super.showHelp(); } } }
Client
public class Client { public static void main(String[] args) { Dialog dialog = new Dialog(); dialog.setPageURL("http://..."); Panel panel = new Panel(); panel.setModalHelpText("This panel does..."); Button ok = new Button("OK"); ok.setTooltipText("This is an OK button that..."); Button cancel = new Button("Cancel"); ok.setNext(panel).setNext(dialog); cancel.setNext(dialog).setNext(panel); ok.showHelp(); cancel.showHelp(); } } # 결과 Tooltip: This is an OK button that... Opening Help Page: http://...
적용
- 프로그램이 다양한 방식과 종류의 요청을 처리할 것으로 예상되지만 정확한 요청 유형과 순서를 미리 알 수 없는 경우
- 특정 순서로 여러 핸들러를 실행해야 하는 경우
- 요청을 처리할 수 있는 핸들러들의 집합과 그 순서가 런타임에 변경되어야 하는 경우
장단점
장점
- 요청의 처리 순서를 제어할 수 있다.
- 단일 책임 원칙. 작업을 호출하는 클래스와 작업을 수행하는 클래스를 분리할 수 있다.
- 개방/폐쇄 원칙. 기존 클라이언트 코드를 수정하지 않고 새 핸들러를 추가할 수 있다.
단점
- 일부 요청들은 처리되지 않을 수 있다.
'STUDY > 디자인패턴' 카테고리의 다른 글
Command Pattern(커맨드 패턴) (0) 2025.01.21 Proxy Pattern(프록시 패턴) (0) 2025.01.07 Flyweight Pattern(플라이웨이트 패턴) (0) 2025.01.07 Facade Pattern(퍼사드 패턴) (0) 2025.01.07 Decorator Pattern(데코레이터 패턴) (0) 2024.12.25