책인 연쇄 패턴이란, 클라이언트의 요청에 따른 처리를 하나의 객체가 담당하는 것이 아니라 여러 객체들로 책임을 나누고 이를 사슬(chain) 처럼 연결해서 연쇄적으로 처리하는 행동 패턴.
예를 들어서, 소비자 센터에 전화하면 음성 로봇 -> 상담원 -> 전문 기술자 순으로 각각 적합한 솔류션을 제공
처리를 담당하는 객체를 핸들러 라고 하고 예시에서는 로봇, 상담원, 기술자가 핸들러가된다.
책임 연쇄 패턴은 조건문(if-else 문 포함)의 요청 처리 로직 자체를 객체화한 것으로 생각
- 반복되는 조건문을 하나의 Handler(interface, 추상클래스)를 생성해서 제거
주어진 url을 여러 조건에 따라서 처리하는 코드를 하나의 코드로 작성한다면 중복되는 기능들이 많이 발생하고 중복되는 if문이 계속해서 발생
중복되는 기능을 하나의 interface로 추상화 하여 해결
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();
}
}
}
}
// 구체적인 핸들러를 묶는 인터페이스 (추상 클래스)
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();
}
}
}
}