Table of Contents
[GoF 디자인 패턴] 책임 연쇄 (Chain of Responsibility) 패턴
책임 연쇄 (Chain of Responsibility) 패턴
행동(behavioral) 패턴 중 하나로, 여러 개의 객체 중에서 요청을 처리할 수 있는 객체를 찾아서 처리하도록 하는 패턴이다.
요청을 처리하는 객체(핸들러)들이 연결된 체인을 이루고 있으며, 요청을 처리할 수 있는 핸들러를 찾을 때까지 체인 상의 모든 핸들러가 요청을 받아서 처리할 수 있는지를 순차적으로 검사한다.
책임 연쇄 패턴 구성요소
- Handler: 요청을 처리하는 메서드를 가진 인터페이스나 추상 클래스.
- ConcreteHandler: 실제로 요청을 처리하는 구현 클래스.
- Client: 요청을 보내는 객체
구현 예제
요청을 처리하는 메서드를 선언하는 Handler 인터페이스를 선언한다.
1public abstract class Manager {
2 protected String name;
3 protected Manager superior;
4
5 public Manager(String name) {
6 this.name = name;
7 }
8
9 public void setSuperior(Manager superior) {
10 this.superior = superior;
11 }
12
13 public abstract void requestApplications(Request request);
14}
각각의 Manager 객체는 superior 변수를 통해 자신의 상사 매니저 객체를 참조하도록 되어 있다. Manager 객체는 스스로 해당 요청을 처리할 수 있는지를 판단하고, 처리할 수 없다면 상사 매니저(superior) 객체에게 해당 요청을 전달한다.
→ “요청을 처리하는 객체들 간의 연결고리 역할을 수행한다.”
실제로 요청을 처리하는 구현 클래스인 ConcreteHandler 클래스를 만든다.
1public class GeneralManager extends Manager {
2
3 public GeneralManager(String name) {
4 super(name);
5 }
6
7 @Override
8 public void requestApplications(Request request) {
9 if (
10 request.getRequestType() == RequestType.PURCHASE &&
11 request.getAmount() < 10
12 ) {
13 System.out.println("GeneralManager 가 처리중입니다 : ");
14 } else {
15 superior.requestApplications(request);
16 }
17 }
18}
19
20public class MiddleManager extends Manager {
21
22 public MiddleManager(String name) {
23 super(name);
24 }
25
26 @Override
27 public void requestApplications(Request request) {
28 if (request.getRequestType() == RequestType.PURCHASE) {
29 System.out.println("MiddleManager 가 처리중입니다 : ");
30 } else {
31 superior.requestApplications(request);
32 }
33 }
34}
35
36public class SuperManager extends Manager {
37
38 public SuperManager(String name) {
39 super(name);
40 }
41
42 @Override
43 public void requestApplications(Request request) {
44 System.out.println("SuperManager 가 처리중입니다 : ");
45 }
46}
각각의 매니저 객체가 requestApplications 메서드를 사용하여 자신이 처리할 수 있는 요청을 처리하고 처리할 수 없을 경우 superior.requestApplications(request);
와 같이 상사 매니저 객체에게 요청을 전달한다.
→ “객체 간의 결합도를 낮출 수 있고, 코드의 유연성과 확장성을 높일 수 있다.”
책임 연쇄 패턴을 사용하는 Client 코드이다.
1Manager manager = new GeneralManager("일반관리자");
2Manager middleManager = new MiddleManager("중간관리자");
3Manager superManager = new SuperManager("슈퍼관리자");
4
5// 다음으로 request 를 넘길 manager 설정
6manager.setSuperior(middleManager);
7middleManager.setSuperior(superManager);
8
9Request purchase = new Request(RequestType.PURCHASE, 1000);
10Request cancel = new Request(RequestType.CANCEL, 10);
11manager.requestApplications(purchase);
12manager.requestApplications(cancel);
setSuperior() 메서드를 사용하여 다음 Manager에게 요청을 전달할 수 있도록 연결고리를 설정한다. GeneralManager 객체의 requestApplications 메소드가 호출되면서 요청을 처리하지 못하면 자신의 상사 매니저에게 요청을 전달한다.
→ “객체 간의 연결고리 설정을 통해 코드의 유연성과 확장성이 높아지며, 객체 간의 결합도를 낮출 수 있다.”
책임 연쇄 패턴 고려사항
객체 간의 결합도를 낮춰야 하거나 요청을 처리할 객체를 동적으로 결정할 때 책임 연쇄 패턴을 사용하면 좋다. 다만 모든 요청을 처리해야 하는 경우나 책임 연쇄가 너무 길어진다면 책임 연쇄 패턴을 사용해서는 안된다.
책임 연쇄 패턴 사용 시 장점
- 객체 간의 결합도를 낮출 수 있다.
- 객체 간의 연결고리를 동적으로 설정하기 때문에 요청 처리를 유연하게 할 수 있다.
책임 연쇄 패턴 사용 시 단점
- 처리할 수 있는 객체가 없는 경우 요청이 처리되지 않을 수 있다. - 요청 처리 보장 X
- 요청을 처리할 객체를 찾기 위해 여러 객체를 검색하는 과정에서 오버헤드가 발생할 수 있다.