개발
home
🔗

[디자인 패턴] 책임 연쇄 패턴

Created
2022/03/07
Tags
Design Pattern
행동 패턴
책임 연쇄 패턴
책임 체인 패턴
2022-03-08 @이영훈

책임 연쇄 패턴

메시지를 보내는 객체와 이를 받아 처리하는 객체들 간의 결합도를 없애기 위한 패턴입니다. 하나의 요청에 대한 처리가 반드시 한 객체에서만 되지 않고, 여러 객체에게 그 처리 기회를 주려는 것입니다.

들어가기 전에

해당 예시는 코드없는 프로그래밍님의 강의를 참고하였습니다
전체 코드는 깃허브를 참고해주세요

결제 모듈 예시

현금 결제, 카드 결제, 카카오페이 결제를 만든다고 할 때 보통의 경우 다음과 같은 코드를 작성하게 됩니다
switch (req.getType()) { case PaymentType.CASH: return cashHandler.handle(req); case PaymentType.CREDIT_CARD: return creditCardHandler.handle(req); case PaymentType.KAKAO_PAY: return kakaoPayHandler.handle(req); }
Java
복사
결제 모듈이 계속 추가되는 경우, 기존 코드가 계속 수정이 되어야 하기 때문에 좋지 않습니다.

책임 연쇄 패턴으로 결제 모듈

PaymentHandler 인터페이스를 선언합니다.
다음에 실행할 handler를 지정하는 함수 setNextHandler와 현재에서 처리할 방식을 선언한 handle 함수가 있습니다.
public interface PaymentHandler { void setNextHandler(PaymentHandler handler); void handle(PaymentRequest req); }
Java
복사
PaymentHandler를 상속한 CashHandler 입니다.
내부적으로 다음 핸들러를 선언할 수 있는 함수를 Override해서 구현하고, 들어오는 요청을 처리하는 함수를 구현했습니다. 예제에서는 쉽게 해당 내용을 print하는 것으로 처리하였습니다.
public class CashHandler implements PaymentHandler { private PaymentHandler nextHandler; @Override public void setNextHandler(PaymentHandler handler) { nextHandler = handler; } @Override public void handle(PaymentRequest paymentRequest) { if (paymentRequest.getPaymentType() == PaymentType.CASH) { System.out.println("CashHandler received " + paymentRequest.getAmount()); return; } if (nextHandler != null) { nextHandler.handle(paymentRequest); } } }
Java
복사
CreditCardHandler입니다. CashHandler와 동일한 구조입니다.
public class CreditCardHandler implements PaymentHandler { private PaymentHandler nextHandler; @Override public void setNextHandler(PaymentHandler handler) { nextHandler = handler; } @Override public void handle(PaymentRequest paymentRequest) { if (paymentRequest.getPaymentType() == PaymentType.CREDIT_CARD) { System.out.println("CreditCardHandler received " + paymentRequest.getAmount()); return; } if (nextHandler != null) { nextHandler.handle(paymentRequest); } } }
Java
복사
KakaoPayHandler입니다. CashHandler와 동일한 구조입니다. 달라지는 건 handle 함수입니다.
public class KakaoPayHandler implements PaymentHandler { private PaymentHandler nextHandler; @Override public void setNextHandler(PaymentHandler handler) { nextHandler = handler; } @Override public void handle(PaymentRequest paymentRequest) { if (paymentRequest.getPaymentType() == PaymentType.KAKAO_PAY) { System.out.println("KakaoPayHandler received " + paymentRequest.getAmount()); return; } if (nextHandler != null) { nextHandler.handle(paymentRequest); } } }
Java
복사

책임 연쇄 실행하기

CashHandler가 모든 처리의 시작으로 설정하였습니다. Cash → CreditCard → KakaoPay 순으로 지정하였습니다. CashHandler를 시작으로 설정하지 않고 시작 핸들러를 만들어도 좋습니다.
public class ChainOfResponsibilityApplication { public static void main(String[] args) { CashHandler cashHandler = new CashHandler(); CreditCardHandler creditCardHandler = new CreditCardHandler(); KakaoPayHandler kakaoPayHandler = new KakaoPayHandler(); // 🐳 다음 순서로 처리함: cash -> credit card -> kakao pay cashHandler.setNextHandler(creditCardHandler); creditCardHandler.setNextHandler(kakaoPayHandler); // 👏 요청 1: 현금, 10_000원 PaymentRequest paymentRequest1 = new PaymentRequest(PaymentType.CASH, 10_000); System.out.println("첫번째 요청: 현금, 10_000원"); cashHandler.handle(paymentRequest1); // CashHandler received 10000 // 👏 요청 2: 신용카드, 20_000원 PaymentRequest paymentRequest2 = new PaymentRequest(PaymentType.CREDIT_CARD, 20_000); System.out.println("두번째 요청: 신용카드, 20_000원"); cashHandler.handle(paymentRequest2); // CreditCardHandler received 20000 // 👏 요청 3: 카카오페이, 30_000원 PaymentRequest paymentRequest3 = new PaymentRequest(PaymentType.KAKAO_PAY, 30_000); System.out.println("두번째 요청: 카카오페이, 30_000원"); cashHandler.handle(paymentRequest3); // KakaoPayHandler received 30000 } }
Java
복사
책임 연쇄 패턴에서는, 시작 PaymentHandler(여기에서는 CashHandler)를 실행시키면 내부 결제 핸들러들이 순차적으로 실행됩니다. 해당 결제 모듈 핸들러가 처리할 수 있는 경우 처리를 하고 결제를 끝냅니다.

Ref.

도서 Gof Design Pattern