정의
- 클라이언트에게 어떠한 요청이 들어왔을 때, 요청을 받은 객체가 해당 요청을 해결할 수 없을 경우 연결된 다음 객체들에 전달하고 해당 요청을 해결할 수 있는 객체가 처리하는 방식입니다. 요청 객체와 처리 객체를 분리하거나 요청을 처리할 수 있는 객체가 여러 개인데 하나의 객체에 요청을 보낼 때 책임 연쇄 패턴을 적용할 수 있습니다. 즉, 요청을 처리할 수 있는 객체가 여러개이고 이러한 처리를 하는 객체가 명시적이지 않을 때 사용할 수 있는 패턴입니다.
쉽게 설명하면
- 어떤 요청이 그 요청을 담당하는 객체에 들어오면 각각의 요청에 대해서 특정한 객체가 담당하는 것이 일반적이지만 객체를 연결리스트와 같은 사슬 방식으로 연결한 후에 요청을 수행하지 못하는 객체라면 다음 객체에 넘기며 책임을 넘기는 형태의 패턴을 말한다.
- A회사 총무과에는 5명의 직원이 있으며, 각각 담당하는 역할이 다르다. 회사원B가 총무과에 요청사항이 있어서 총무과에 전화를 걸었다. 담당자1이 전화를 받았다. 담당자1은 용건을 듣더니 자기가 담당자가 아니라면서 담당자2를 연결해 주었다. 담당자2도 자신의 담당 업무가 아니라서 담당자3을 연결해 주었다. 담당자3은 자신의 업무가 맞다면서 업무를 처리해 주고 전화를 끊었다.
목적
이 패턴은 결합을 느슨하게 하기 위해 고안되었으며 가장 좋은 프로그래밍 사례로 꼽힌다. 요청을 보내는 객체와 이를 처리하는 객체간의 결합도를 느슨하게 하기 위한 방법이며 여러 객체에 처리 기회를 준다.
장점
- 호출 객체(client 요청을 하는 객체)와 처리 객체(요청받는 객체 handler) 분리할 수 있다.
- 호출 객체(client)는 처리 객체의 체인(사슬) 구조를 몰라도 되며, 체인 내부의 연결에 대한 레퍼런스도 알 필요가 없어서 느슨한 연결이 된다.
- 체인에 들어가는 객체를 추가, 삭제, 변경도 가능하도록 구성할 수 있어서(링크드 리스트) 역할을 동적으로 추가,삭제 가능하다.
단점
- 처리 객체들 내부에서 사이클이 발생할 수 있다.(무한 순환)
- 실행 과정을 살펴보거나, 디버깅하기 힘들다.
- 요청을 처리할 객체가 chain의 어느 위치에 있을지는 동적이기 때문에 시간 예측이 어렵습니다.
특징 및 활용
- 요청이 반드시 수행된다는 보장이 없다. 이 특징은 장점도 단점도 될 수 있다.
- 마우스 클릭이나 키보드 이벤트를 처리할 때 흔히 사용된다.
특징 및 활용
화면 이벤트 처리
다이어그램
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)) {
doSomething(number);
} else if (next != null) {
next.handleRequest(number);
} else {
System.out.println("처리할 수 있는 객체 없음");
}
}
public void doSomething(int number) {
System.out.println(name + "(으)로 처리");
}
public abstract boolean canHandle(int number);
}
public class EvenHandler extends Handler {
public EvenHandler() {
super("짝수");
}
public boolean canHandle(int number) {
return number % 2 == 0;
}
@Override
public void doSomething(int number) {
System.out.println(number + ":" + name + "로 처리");
}
}
public class OddHandler extends Handler {
public OddHandler() {
super("홀수");
}
public boolean canHandle(int number) {
return number % 2 != 0;
}
@Override
public void doSomething(int number) {
System.out.println(number + ":" + name + "로 처리");
}
}
public class Tester {
public static void main(String[] args) {
Handler oddHandler = new OddHandler();
Handler evenHandler = new EvenHandler();
oddHandler.setNext(evenHandler);
for(int i = 1; i < 10; i++) {
oddHandler.handleRequest(i);
}
}
}
'프로그래밍 > OOP_Pattern_TDD' 카테고리의 다른 글
디자인패턴 중재자 패턴 (Mediator Pattern) (0) | 2022.08.01 |
---|---|
디자인패터 플라이웨이트 패턴 (Flyweight pattern) (0) | 2022.08.01 |
디자인패턴 빌더 패턴(Builder Pattern) (0) | 2022.07.29 |
디자인패턴 Bridge Pattern (브릿지 패턴) (0) | 2022.07.29 |
디자인 패턴 범주별 분류 (0) | 2022.07.28 |