HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
📝
남득윤 학습 저장소
/
객체 지향 프로그래밍
객체 지향 프로그래밍
/
디자인 패턴
디자인 패턴
/
⛓️
Chain of Responsibility Pattern
⛓️

Chain of Responsibility Pattern

Motivation

다른 클래스에게 책임을 넘겨야하는 경우가 있다.
  • beginner approach - 전부 퍼블릭으로 만들기
  • expert approach - using the 책임 연쇄 패턴
 
책임연쇄패턴을 사용하면 어떤 객체가 수행할지는 모른체 명령을 날릴수 있다. 한 객체는 누가 실행할지는 모르지만 일단 요청을 전달한다.
요청을 전달받은 객체는
  1. 직접 처리하거나
  1. 다른 객체에게 넘기거나
  1. 둘다 할 수 있다.
 
자판기의 동전 구멍이 책임연쇄패턴의 예시이다. 동전별로 구멍이 있는것이 아니라 동전 구멍은 딱 하나만 있다. 동전의 적절한 위치는 명령의 수신자가 결정한다. (수신자 = 저울???)

Intent

  • 요청을 하는 객체(Client)와 실제 요청을 처리하는 객체를 분리하여 클라이언트와 실질 처리 로직을 분리한다.
  • 객체는 체인의 일부가 된다. 요청을 처리 될때까지 객체의 체인을 따라 전달된다.

Implementation

notion image
  • 핸들러 - 요청을 처리하는 방식에 대한 인터페이스 제공
  • 구체 핸들러 - 요청 처리 로직 제공
  • 클라이언트 - 체인의 첫번째 핸들러에게 Command 날림
 
Code Example
 
package oodesign.design.behavioral.chainofresponsiblity; class Request { private int m_value; private String m_description; public Request(String description, int value) { m_description = description; m_value = value; } public int getValue() { return m_value; } public String getDescription() { return m_description; } } abstract class Handler { protected Handler m_successor; public void setSuccessor(Handler successor) { m_successor = successor; } public abstract void handleRequest(Request request); } class ConcreteHandlerOne extends Handler { public void handleRequest(Request request) { if (request.getValue() < 0) { //if request is eligible handle it System.out.println("\tConcreteHandlerOne.HandleRequest : " + request.getDescription() + request.getValue()); } else { super.m_successor.handleRequest(request); } } } class ConcreteHandlerThree extends Handler { public void handleRequest(Request request) { if (request.getValue() >= 0) { //if request is eligible handle it System.out.println("\tConcreteHandlerThree.HandleRequest : " + request.getDescription() + request.getValue()); } else { super.m_successor.handleRequest(request); } } } class ConcreteHandlerTwo extends Handler { public void handleRequest(Request request) { if (request.getValue() > 0) { //if request is eligible handle it System.out.println("\tConcreteHandlerTwo.HandleRequest : " + request.getDescription() + request.getValue()); } else { super.m_successor.handleRequest(request); } } } public class Main { public static void main(String[] args) { // Setup Chain of Responsibility Handler h1 = new ConcreteHandlerOne(); Handler h2 = new ConcreteHandlerTwo(); Handler h3 = new ConcreteHandlerThree(); h1.setSuccessor(h2); h2.setSuccessor(h3); // Send requests to the chain h1.handleRequest(new Request("Negative Value ", -1)); h1.handleRequest(new Request("Zero Value ", 0)); h1.handleRequest(new Request("Positive Value ", 1)); } }
ConcreteHandlerOne.HandleRequest : Negative Value -1 ConcreteHandlerThree.HandleRequest : Zero Value 0 ConcreteHandlerTwo.HandleRequest : Positive Value 1 Process finished with exit code 0
세개의 핸들러가 체인을 이루고 있다.
ConcreteHandlerOne → ConcreteHandlerTwo → ContreteHandlerThree
음수처리 → 양수 처리 → 0 처리

Applicablity

책임 연쇄 패턴을 적절하게 사용할 수 있는 경우
  • 두개 이상의 객체가 명령을 처리할 수 있을때
  • 핸들러가 이미 알려져 있지 않은 경우
  • 핸들러가 자동으로 결정해야 하는경우
  • 여러 객체를 처리할 방법을 동적으로 결정해야 하는 경우

Examples

  • 너무 많다.

Specific problems & Implementation

 
  • 핸들러가 처리할 수 있는 요청에 대한 인터페이스를 정의하자.
  • 체인의 끝에 처리되지 않은 요청이 있는지 확인하자