책임 연쇄 패턴(Chain of Responsibility Pattern)은 행동 패턴 중 하나로
행동 패턴은 주로 객체 간의 상호작용에 초점을 맞춥니다. 이러한 상호작용은 객체들이 서로 메시지를 전송하고 그에 따라 동작을 변경하거나 실행하는 방식을 나타냅니다. 행동 패턴은 이러한 객체 간의 상호작용을 효율적으로 설계하기 위한 다양한 전략과 구조를 제공합니다.
책임 연쇄 패턴이란?
책임 연쇄 패턴(Chain of Responsibility)은 객체들이 연결된 체인 형태로 존재하며, 각 객체가 요청을 처리하지 못할 경우 다음 객체에게 책임을 전달하고, 다음 객체 또한 처리하지 못하면 다시 다음 객체로 전달하는 패턴입니다.
이 패턴은 객체 간의 결합도를 낮추고, 요청을 처리할 객체를 동적으로 결정하는 데 유용합니다. 요청 처리 과정에서 요청을 처리할 객체를 직접 지정하지 않아도 되므로, 클라이언트 코드와 서버 코드 간의 결합도가 낮아집니다.
예를 들어 로그인 처리나 예외 처리와 같은 경우에 유용하게 사용될 수 있습니다. 이를 통해 요청 처리 과정에서 각 객체가 책임을 나누어 처리할 수 있으므로, 코드 유지 보수성과 확장성을 높일 수 있습니다.
책인 연쇄 패턴 구조

요청을 수신하고 처리 객체들의 집합을 정의하는 인터페이스
요청을 처리하는 실제 처리 객체
핸들러에 대한 필드를 내부에 가지고 있으며 메서드를 통해 다음 핸들러를 체인시키고 다음 바라본다.
자신이 처리할 수 없는 요구가 나오면 바라보고 있는 다음 체인의 핸들러에게 요청을 떠넘긴다.
ConcreteHandler1 - ConcreteHandler2 - ConcreteHandler3 - ... 이런식으로 체인 형식이 구성되게 된다.
요청을 Handler 전달한다
책임 연쇄 패턴 코드
책임 연쇄 패턴(미적용)
class UrlParser {
public static void run(String url) {
// protocol 파싱
int index = url.indexOf("://");
if (index != -1) {
System.out.println("PROTOCOL : " + url.substring(0, index));
} else {
System.out.println("NO PROTOCOL");
}
// domain 파싱
int startIndex = url.indexOf("://");
int lastIndex = url.lastIndexOf(":");
System.out.print("DOMAIN : ");
if (startIndex == -1) {
if (lastIndex == -1) {
System.out.println(url);
} else {
System.out.println(url.substring(0, lastIndex));
}
} else if (startIndex != lastIndex) {
System.out.println(url.substring(startIndex + 3, lastIndex));
} else {
System.out.println(url.substring(startIndex + 3));
}
// port 파싱
int index2 = url.lastIndexOf(":");
if (index2 != -1) {
String strPort = url.substring(index2 + 1);
try {
int port = Integer.parseInt((strPort));
System.out.println("PORT : " + port);
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
}
}
class Client {
public static void main(String[] args) {
String url1 = "http://www.youtube.com:80";
System.out.println("INPUT: " + url1);
UrlParser.run(url1);
String url2 = "https://www.inpa.tistory.com:443";
System.out.println("INPUT: " + url2);
UrlParser.run(url2);
String url3 = "http://localhost:8080";
System.out.println("INPUT: " + url3);
UrlParser.run(url3);
}
}
책임 연쇄 패턴(적용)
// 구체적인 핸들러를 묶는 인터페이스 (추상 클래스)
abstract class Handler {
// 다음 체인으로 연결될 핸들러
protected Handler nextHandler = null;
// 생성자를 통해 연결시킬 핸들러를 등록
public Handler setNext(Handler handler) {
this.nextHandler = handler;
return handler; // 메서드 체이닝 구성을 위해 인자를 그대로 반환함
}
// 자식 핸들러에서 구체화 하는 추상 메서드
protected abstract void process(String url);
// 핸들러가 요청에 대해 처리하는 메서드
public void run(String url) {
process(url);
// 만일 핸들러가 연결된게 있다면 다음 핸들러로 책임을 떠넘긴다
if (nextHandler != null)
nextHandler.run(url);
}
}
class ProtocolHandler extends Handler {
@Override
protected void process(String url) {
int index = url.indexOf("://");
if (index != -1) {
System.out.println("PROTOCOL : " + url.substring(0, index));
} else {
System.out.println("NO PROTOCOL");
}
}
}
class DomianHandler extends Handler {
@Override
protected void process(String url) {
int startIndex = url.indexOf("://");
int lastIndex = url.lastIndexOf(":");
System.out.print("DOMAIN : ");
if (startIndex == -1) {
if (lastIndex == -1) {
System.out.println(url);
} else {
System.out.println(url.substring(0, lastIndex));
}
} else if (startIndex != lastIndex) {
System.out.println(url.substring(startIndex + 3, lastIndex));
} else {
System.out.println(url.substring(startIndex + 3));
}
}
}
class PortHandler extends Handler {
@Override
protected void process(String url) {
int index = url.lastIndexOf(":");
if (index != -1) {
String strPort = url.substring(index + 1);
try {
int port = Integer.parseInt((strPort));
System.out.println("PORT : " + port);
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
}
}
class Client {
public static void main(String[] args) {
// 1. 핸들러 생성
Handler handler1 = new ProtocolHandler();
Handler handler2 = new DomianHandler();
Handler handler3 = new PortHandler();
// 2. 핸들러 연결 설정 (handler1 → handler2 → handler3)
handler1.setNext(handler2).setNext(handler3);
// 3. 요청에 대한 처리 연쇄 실행
String url1 = "http://www.youtube.com:80";
System.out.println("INPUT: " + url1);
handler1.run(url1);
System.out.println();
String url2 = "https://www.inpa.tistory.com:443";
System.out.println("INPUT: " + url2);
handler1.run(url2);
System.out.println();
String url3 = "http://localhost:8080";
System.out.println("INPUT: " + url3);
handler1.run(url3);
}
}
[디자인 패턴] 책임 연쇄 패턴(Chain of Responsibility Pattern)
[Design Pattern] Chain of Responsibility(책임 연쇄) 패턴이란?