제 홈페이지의 모든 글은 anti-nhn license에 따릅니다.



자바 디자인 패턴 9 - Chain of Responsibility

1. Chain of Responsibility 패턴은..

오션스 일레븐과 같은 류의 영화를 보신 적이 있죠? 전문가들이 몇 명 있습니다. 그러나, 그 전문가들은 할 수 있는 일이 극히 제한되어 있죠. 예를 들어, 해커가 격투에 능하진 않습니다. 해커는 단지 해킹에만 능합니다. 그들은 각각은 할 수 있는 일들이 제한적이지만, 모여있으면 세상만사 다 해결합니다. 각각의 전문가들이 자기가 할 수 있는 일만 하면 되거든요. 만약에 그들 모두가 해결할 수 없는 문제가 발생하면... 오션스 투엘브가 되고, 오션스 써틴이 되고 하면 됩니다. 또 영입하면 되죠 멀..
Chain of Responsiblity 패턴에서는 문제 해결사들이 한줄로 쫙 서있다가 문제가 들어오면, 자기가 해결할 수 있으면 해결하고, 안 되면 다음 해결사에게 문제를 넘겨버립니다.

2. 예제

------------------ 전문가: 상위 클래스 ---------------

package ch09_ChainOfResponsibility;
public abstract class Expert {
    private Expert next;
    protected String expertName;
    public final void support(Problem p){
        if (solve(p)) {
           System.out.println(expertName+ "이(가) " + p.getProblemName()  +"을(를) 해결해 버렸네.");
        }else{
            if (next != null) {
                next.support(p);
            }else{
                System.out.println(p.getProblemName() + "은(는) 해결할 넘이 없다.");
            }
        }
    }
    public Expert setNext(Expert next){
        this.next = next;
        return next;
    }
    protected abstract boolean solve(Problem p);
}

----------- 전문가들이 풀어야할 문제 클래스 -----------

package ch09_ChainOfResponsibility;
public class Problem {
    private String problemName;
    public Problem(String name) {
        this.problemName = name;
    }
    public String getProblemName() {
        return problemName;
    }
}

--------------- 첫번째 전문가 파이터! --------

package ch09_ChainOfResponsibility;
public class Fighter extends Expert {
    public Fighter(){
        this.expertName = "격투가";
    }
    @Override
    protected boolean solve(Problem p) {
        return p.getProblemName().contains("깡패");
    }
}

--------------- 두번째 전문가 해커! --------

package ch09_ChainOfResponsibility;
public class Hacker extends Expert {
    public Hacker(){
        this.expertName = "해커";       
    }
    @Override
    protected boolean solve(Problem p) {
        return p.getProblemName().contains("컴퓨터");
    }
}

--------------- 세번째 전문가 카사노바! --------

package ch09_ChainOfResponsibility;
public class Casanova extends Expert {
    public Casanova(){
        expertName = "카사노바";
    }
    @Override
    protected boolean solve(Problem p) {
        return p.getProblemName().contains("여자") || p.getProblemName().contains("여성");
    }
}

----------------- 테스트 클래스 ------------------

package ch09_ChainOfResponsibility;
public class Test {
    public static void main(String[] args) {
        Problem[] problems = new Problem[5];
        problems[0] = new Problem("덩치 큰 깡패");
        problems[1] = new Problem("컴퓨터 보안장치");
        problems[2] = new Problem("까칠한 여자");
        problems[3] = new Problem("날렵한 깡패");
        problems[4] = new Problem("폭탄");
       
        Expert fighter = new Fighter();
        Expert hacker = new Hacker();
        Expert casanova = new Casanova();
       
        fighter.setNext(hacker).setNext(casanova);
       
        for (Problem problem : problems) {
            fighter.support(problem);
        }
    }
}

--------------- 결과 ----------------

격투가이(가) 덩치 큰 깡패을(를) 해결해 버렸네.
해커이(가) 컴퓨터 보안장치을(를) 해결해 버렸네.
카사노바이(가) 까칠한 여자을(를) 해결해 버렸네.
격투가이(가) 날렵한 깡패을(를) 해결해 버렸네.
폭탄은(는) 해결할 넘이 없다.


등장인물들은 전부 테스트 클래스에 있습니다. 5개의 문제점들이 있고, 3명의 전문가들이 있죠. 테스트 클래스에서는 어떤 전문가가 어떤 문제를 해결하는 지는 관심 없습니다. "문제는 해결만 되면 된다!"가 클라이언트인 테스트 클래스의 입장입니다.

Expert 클래스는 마치 Decorator 패턴 처럼 Expert를 멤버 변수로 가지고 있습니다. 그러나 Decoarator와는 달리 그 값이 null일 수도 있습니다. 다음 전문가가 없을 수도 있는 거죠. 위의 코드에서는 casanova가 마지막 전문가입니다. 즉, casanova는 next라는 변수 값이 null입니다.
일반적인 set머시기 하는 메쏘드들은 리턴 타입이 void인데, 여기서는 리턴 타입이 Expert입니다. 예제코드처럼 전문가 그룹을 연결시키는 코드를 한줄로 만들기 위해서입니다. 만약 리턴 타입이 void였다면, 황토색 부분은 아래와 같이 두 줄로 바뀔 것입니다.

fighter.setNext(hacker);
hacker.setNext(casanova);

Expert 클래스의 support() 가 하는 일은 자기가 해결할 수 있으면 하고, 못하면 다음 전문가한테 넘기고, 떠넘길 다음 전문가가 없으면, 못한다고 생떼를 쓰는 겁니다. 내부적으로 sovle()메쏘드를 호출합니다.
solve()는 각각의 개별 클래스별로 자기가 해결 가능한지 불가능한지를 판단하는 매쏘드입니다. 당연히 구체적으로 기술해야 하므로 하위 객체에 떠넘깁니다.

3. Chain of Responsibility의 특징

위의 예제에서는 폭탄 앞에 전문가들이 좌절해야 했습니다. 기존에 있던 애들은 그대로 두고, 폭탄전문가를 한 명 영입하면 일이 해결될 것 같습니다. 폭탄전문가 클래스를 새로 만들어서 테스트 클래스에 넣어주면 일이 해결됩니다. 또 별로 쓸모 없는 전문가를 영입했을 때는 짜르기도 쉽습니다. 전체적인 로직이 바뀌지 않습니다.

템플릿 메쏘드가 숨어있습니다. 테스트 클래스에서는 각 전문가클래스의 solve() 메쏘드를 호출한 적이 없지만, 내부적으로 호출이 됩니다.

문제가 나타났을 때 어떤 전문가가 해결할 것인지 단번에 결정이 되지 않습니다. 일단 모든 문제는 fighter 객체를 거쳐갑니다. 맨 앞에 있으니까요. 따라서 전문가 객체의 순서가 전체적인 수행 속도에 영향을 끼칠 수 있습니다. 가능한한 일반적인 문제해결사들을 앞쪽에 세워두는 게 좋습니다.

4. JAVA API에 있는 Chain of Responsibility

JAVA 1.0의 GUI 에서는 Chain of Responsibility를 사용했었다고 하는군요. 이벤트가 발생했을 때 자기가 해결할 수 있는 지 보고 해결이 안되면 상위 컴포넌트로 던졌다네요. (확인한 적은 없습니다만, 대충 말은 되는 것 같군요.)

by 삼실청년 | 2007/10/18 14:55 | 컴터질~ | 트랙백 | 핑백(3) | 덧글(7)

트랙백 주소 : http://iilii.egloos.com/tb/3863886
☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]
Linked at 건실성실착실 3실 청년! : .. at 2011/11/25 13:36

... 비에 저장하고, 캐쉬에도 저장하고 끝 2번 입장에서는 디비에서 조회를 해왔든 구글 가서 가져왔든 캐쉬에 저장한다는 것은 동일합니다. 이것을 chain of responsibility 패턴을 이용해서 정리하면 깔끔해집니다. 각각의 chain은 다음과 같이 정의 됩니다. 체인 이름 조회 방법 이전 단계 성공시 하는 일Ca ... more

Linked at java design patt.. at 2017/05/31 09:26

... nbsp;8. 자바 디자인 패턴 8 – Decorator 9. 자바 디자인 패턴 9 <a href="http://blog.sina.com.cn/s/blog_8e40db350102wt27.html">港股开户</a> &#8211; Chain of Responsibility 10. 자바 디자인 패턴 10 – Facade&n ... more

Linked at 자바 디자인 패턴 종류 &#8.. at 2017/09/26 09:15

... – Strategy 7. 자바 디자인 패턴 7 – Composite 8. 자바 디자인 패턴 8 – Decorator 9. 자바 디자인 패턴 9 &#8211; Chain of Responsibility 10. 자바 디자인 패턴 10 – Facade 11. 자바 디자인 패턴 11 – Observer 12. 자바 ... more

Commented by 지송 at 2009/08/20 09:39
아 이해가 참편해서 좋습니다.
링크를 잊어버렸다가 다시 찾아왔습니다. ㅎㅎ
여름 건강하세요.
Commented by 삼실청년 at 2009/08/22 05:39
아핫~ 고맙습니다. 안 그래도 감기에.. 쿨럭~
4년간 감기 한 번도 안 걸렸는데, 올 초에 걸리더니, 여름에 또 걸리네요.
나이는 숫자에 불과한 게 아닐지도 모른다는 생각이 엄습해옵니다.ㅜㅜ
건강하세요~
Commented by 목아파요 at 2009/12/31 15:30
잘 보고 있습니다.

님은 확실히 패턴에 대해 잘 이해하고 있는것 같네요

ㅋㅋ 수고하세요

짐 잘 보고 있습니다.
Commented by 삼실청년 at 2010/01/04 23:15
잘 이해하긴요. 책 뒤적이고 싸이트 뒤적여서 제가 이해한 만큼만 겨우겨우 썼던 겁니다.

새해 복 많이 받으세요~^^
Commented by flypizza at 2013/07/04 17:19
역할 사슬의 장점 첫번째가 "요청을 보낸 쪽하고 받는 쪽을 분리시킬 수 있습니다" 헤드퍼스트 디자인 패턴 책에 쓰여있습니다. 그런데, 현재 위의 예제는 그런 장점을 고려하지 않은 것 같습니다. 전문가들을 테스트 클래스에서 전부 생성시키고, 그것의 순서를 정해주고 계시네요. 그렇게 되면, 이 '전문가'에 대한 것들을 전부 알고 있어야 하지 않나요?
제가 지금 공부중이라서 잘은 모릅니다. 그래서 질문하는 거구요. 제 생각에는 매니저 클래스 하나가 모든 전문가들의 전문가를 갖고, 그 매니저 클래스 하나만 생성시켜야 한다고 봅니다. 헤깔립니다.
Commented by 삼실청년 at 2013/07/07 07:24
보통은 chain을 감싸는 클래스를 만들어서 singleton 으로 쓰거나 첫번째 chain만 외부로 공개해서 씁니다.
여기서 chain을 만드는 부분이 singleton같은 걸로 분리가 안 되어 있는 이유는
1. 코드가 길어지니까.
2. 다른 패턴이랑 섞여서 얘의 본질을 이해하기 어렵게 만들까봐.
입니다.

chain of responsibility 의 핵심은 역할을 사슬로 만드는 것입니다. 저는 예제를 linked list의 구조로 했지만 array 건 set이건 그런 것이 핵심은 아닙니다.

jdk 에서는 jdbc로딩하는 부분에 chain of reponsibility 패턴이 들어가 있습니다. 각 패턴의 핵심만 이해하시고 소스 한번 까보시면 도움이 많이 될 듯 합니다.
Commented by 질문자 at 2016/06/22 16:09
예외처리에 응용하면 괜찮을 것 같네요

:         :

:

비공개 덧글

◀ 이전 페이지          다음 페이지 ▶