// ❌ 나쁜 예: 요청 처리자가 고정된 코드
public class HelpSystem {
public void handleHelp(String context) {
// 구체적인 처리자에 직접 의존
if (context.equals("button")) {
buttonHelp.showHelp();
} else if (context.equals("dialog")) {
dialogHelp.showHelp();
} else if (context.equals("application")) {
appHelp.showHelp();
}
}
}
문제점:
abstract class Handler {
protected Handler successor; // 다음 처리자 참조
public void setSuccessor(Handler successor) {
this.successor = successor;
}
public abstract void handleRequest(int request);
}
왜 Abstract Class인가?
successor 필드와 setSuccessor() 메서드는 모든 핸들러에서 동일하게 사용handleRequest()는 서브클래스에서 구현하도록 강제class ConcreteHandler1 extends Handler {
public void handleRequest(int request) {
if (canHandle(request)) {
// 직접 처리
} else if (successor != null) {
successor.handleRequest(request); // 다음으로 전달
}
}
}
공통 구현 존재
// ✅ 모든 Handler가 동일하게 사용하는 코드
protected Handler successor;
public void setSuccessor(Handler successor) {
this.successor = successor;
}
체인 연결 로직 재사용
상태(successor) 유지 필요
// Java 8+ default method 활용 시
public interface Handler {
Handler getSuccessor();
void setSuccessor(Handler successor);
default void passToNext(Request request) {
if (getSuccessor() != null) {
getSuccessor().handleRequest(request);
}
}
void handleRequest(Request request);
}

Client → Handler1 → Handler2 → Handler3 → ... → null
↓ ↓ ↓
처리 가능? 처리 가능? 처리 가능?
↓ ↓ ↓
Yes: 처리 Yes: 처리 Yes: 처리
No: 전달 No: 전달 No: 종료(미처리)
핵심 특징:
// 추상 핸들러
abstract class Handler {
protected Handler successor; // 다음 처리자
// 다음 처리자 설정
public void setSuccessor(Handler successor) {
this.successor = successor;
}
// 요청 처리 (서브클래스에서 구현)
public abstract void handleRequest(int request);
}
// 0~9 범위 처리
class ConcreteHandler1 extends Handler {
public void handleRequest(int request) {
if (request >= 0 && request < 10) {
System.out.println("Handler1이 처리: " + request);
} else if (successor != null) {
successor.handleRequest(request); // 다음으로 전달
}
}
}
// 10~19 범위 처리
class ConcreteHandler2 extends Handler {
public void handleRequest(int request) {
if (request >= 10 && request < 20) {
System.out.println("Handler2가 처리: " + request);
} else if (successor != null) {
successor.handleRequest(request);
}
}
}
// 20~29 범위 처리
class ConcreteHandler3 extends Handler {
public void handleRequest(int request) {
if (request >= 20 && request < 30) {
System.out.println("Handler3이 처리: " + request);
} else if (successor != null) {
successor.handleRequest(request);
}
}
}
public class MainApp {
public static void main(String[] args) {
// 핸들러 생성
Handler h1 = new ConcreteHandler1();
Handler h2 = new ConcreteHandler2();
Handler h3 = new ConcreteHandler3();
// 체인 연결: h1 → h2 → h3
h1.setSuccessor(h2);
h2.setSuccessor(h3);
// 요청 처리 (항상 체인의 시작점에 요청)
int[] requests = {2, 5, 14, 22, 18, 3, 27, 20};
for (int request : requests) {
h1.handleRequest(request);
}
}
}
Handler1이 처리: 2
Handler1이 처리: 5
Handler2가 처리: 14
Handler3이 처리: 22
Handler2가 처리: 18
Handler1이 처리: 3
Handler3이 처리: 27
Handler3이 처리: 20
// 도움말 핸들러 추상 클래스
abstract class HelpHandler {
protected HelpHandler successor;
public void setSuccessor(HelpHandler successor) {
this.successor = successor;
}
public abstract void handleHelp();
}
// 버튼 도움말 (가장 구체적)
class ButtonHelp extends HelpHandler {
private boolean hasHelp;
public ButtonHelp(boolean hasHelp) {
this.hasHelp = hasHelp;
}
public void handleHelp() {
if (hasHelp) {
System.out.println("버튼 도움말: 이 버튼은 인쇄를 실행합니다.");
} else if (successor != null) {
successor.handleHelp(); // 도움말 없으면 상위로 전달
}
}
}
// 다이얼로그 도움말
class DialogHelp extends HelpHandler {
public void handleHelp() {
System.out.println("다이얼로그 도움말: 인쇄 설정 창입니다.");
}
}
// 애플리케이션 도움말 (가장 일반적)
class ApplicationHelp extends HelpHandler {
public void handleHelp() {
System.out.println("앱 도움말: 일반적인 사용 방법입니다.");
}
}
// 사용
public class HelpSystem {
public static void main(String[] args) {
// 체인: Button → Dialog → Application
HelpHandler appHelp = new ApplicationHelp();
HelpHandler dialogHelp = new DialogHelp();
HelpHandler buttonHelp = new ButtonHelp(false); // 버튼에 도움말 없음
buttonHelp.setSuccessor(dialogHelp);
dialogHelp.setSuccessor(appHelp);
// 버튼에서 도움말 요청 → 다이얼로그 도움말 출력
buttonHelp.handleHelp();
}
}
| 요소 | 역할 | 특징 |
|---|---|---|
| Handler | 요청 처리 인터페이스 + successor 관리 | Abstract Class (공통 구현 제공) |
| ConcreteHandler | 실제 요청 처리 또는 전달 | 자신의 처리 범위 판단 |
| Client | 체인의 시작점에 요청 전송 | 누가 처리하는지 모름 |
| 패턴 | 관계 |
|---|---|
| Composite | 부모-자식 관계를 successor 체인으로 활용 가능 |
| Command | 요청을 객체로 캡슐화하여 COR에서 전달 |
| Observer | 둘 다 송신자-수신자 분리, 다른 트레이드오프 |