2011년 5월 23일 월요일

The Chain of Responsibility Pattern

13. The Chain of Responsibility Pattern
Chain of Responsibility 패턴은 다수의 클래스가 다른 클래스의 처리 능력을 파악하지 않은 상태에서 요청 내용을 처리할 수 있게 하는 패턴이다. 이 패턴은 이런 클래스들을 아주 세밀하게 결합하도록 한다. 이때 유일한 공통 링크는 해당 클래스 간에 전달되는 요청 내용일 뿐이다. 요청 내용은 해당 클래스들 중 하나가 요청 내용을 처리할 때까지 계속해서 전달 된다.
구조
*


역할
  • Handler : Request를 처리하기 위한 인터페이스를 정의한다. Successor 링크를 구현한다.
  • Concrete Handler : 자신이 책임지고 있는 request를 처리한다. successor에 접근할 수 있다. Request를 처리할 수 있으면 그렇게 하고, 아니면 successor에게 전달한다.
  • Client : Request를 만들어 체인 상의 첫 ConcreteHandler에게 전달한다.

의도
어떤 request에 대해서 한 개 이상의 오브젝트에게 처리할 기회를 줌으로써, 그 request의 sender와 receiver를 decoupling한다. Receiver가 될 수 있는 오브젝트들을 연결하여 체인을 만들고, request가 처리될 때 까지 체인을 따라 전달한다.
적용시기
  • 프로그램이 요구하는 작업에 적합한 유사한 메소드들을 여러 개의 객체가 가질 경우, 그러나 개발자가 호출 코드에 객체의 역할을 지정해 주기보다는 객체가 스스로 처리 작업을 결정하도록 하는 것이 좀더 바람직하다.
  • 객체들 중 한가지가 가장 적합할 경우, 그러나 특정 객체를 선택하기 위해 if-else문이나 switch 문을 사용하여 코드를 작성하고 싶지 않을 경우
  • 프로그램이 실행중일 때 일련의 프로세싱 옵션을 추가하려는 새로운 객체가 존재할 경우
  • 때때로 한 개 이상의 객체가 요청에 따라 작업을 수행해야 할 경우 그리고 개발자는 호출하는 프로그램이 이런 상호 작용 정보를 포함하려고 하지 않을 경우

결론
  • 이 패턴의 1차적인 목적은 다른 패턴들처럼 객체 간의 의존성을 약화시키는 것이다. 따라서 하나의 객체는 다른 객체에게 요청 내용을 전달하는 방법만 파악해 두면 된다.
  • 체인 안의 각각의 자바 객체는 자체적으로 내장되어 있다. 각 객체들은 다른 객체에 대한 정보는 전혀 없고, 자신이 요청 내용을 충족시킬 수 있는지의 여부를 결정할 수 있는 능력만 보유하면 된다. 이런 점은 각각의 객체를 작성하는 일뿐만 아니라 체인을 생성하는 작업을 매우 쉽게 한다.
  • 개발자는 체인 안에서 마지막 객체가 전달한 모든 요청 내용을 처리할 수 있는지 또는 해당 요청 사항을 단지 무시해 버리는지를 판단할 수 있다. 그러나 이와 같은 작업을 효율적으로 수행하려면, 개발자가 해당 체인의 마지막 객체가 어느 객체인지 파악하고 있어야 한다.
  • 마지막으로 자바 언어는 다중 상속을 허용하지 않으므로 기본 chain 클래스는 각각의 객체들이 다른 계층 구조를 상속할 수 있도록 abstract 클래스보다는 인터페이스를 필요로 하게 된다. 이런 접근은 각각의 모듈에서 코드 내용을 링크하고, 전송하며, 전달하는 작업을 개별적으로 구현해야 한다는 것이 단점이다. (또는 이번 예제처럼 chain 인터페이스를 구현하는 concrete 클래스를 서브 클래스화 하는 경우도 포함된다.)

예제소스



예제 소스
public abstract class Support {
private String name;
private Support next;
public Support(String name) {
this.name = name;
}
public Support setNext(Support next) {
this.next = next;
return next;
}
public final void support(Trouble trouble) {
if (resolve(trouble)) {
done(trouble);
} else if (next != null) {
next.support(trouble);
} else {
fail(trouble);
}
}
public String toString() {
return "[" + name + "]";
}
protected abstract boolean resolve(Trouble trouble);
protected void done(Trouble trouble) {
System.out.println(trouble + " is resolved by " + this + ".");
}
protected void fail(Trouble trouble) {
System.out.println(trouble + " cannot be resolved.");
}
}
public class LimitSupport extends Support {
private int limit;
public LimitSupport(String name, int limit) {
super(name);
this.limit = limit;
}
protected boolean resolve(Trouble trouble) {
if (trouble.getNumber() < limit) {
return true;
} else {
return false;
}
}
}
public class NoSupport extends Support {
public NoSupport(String name) {
super(name);
}
protected boolean resolve(Trouble trouble) {
return false;
}
}
public class OddSupport extends Support {
public OddSupport(String name) {
super(name);
}
protected boolean resolve(Trouble trouble) {
if (trouble.getNumber() % 2 == 1) {
return true;
} else {
return false;
}
}
}
public class SpecialSupport extends Support {
private int number;
public SpecialSupport(String name, int number) {
super(name);
this.number = number;
}
protected boolean resolve(Trouble trouble) {
if (trouble.getNumber() == number) {
return true;
} else {
return false;
}
}
}
public class Trouble {
private int number;
public Trouble(int number) {
this.number = number;
}
public int getNumber() {
return number;
}
public String toString() {
return "[Trouble " + number + "]";
}
}
public class mainClass {
public static void main(String[] args) {
mainClass client = new mainClass();
client.exec();
}
public void exec() {
Support alice = new NoSupport("Alice");
Support bob = new LimitSupport("Bob", 100);
Support charlie = new SpecialSupport("Charlie", 429);
Support diana = new LimitSupport("Diana", 200);
Support elmo = new OddSupport("Elmo");
Support fred = new LimitSupport("Fred", 300);
alice.setNext(bob).setNext(charlie).setNext(diana).setNext(elmo).setNext(fred);
for (int i = 0; i < 500; i += 33) {
alice.support(new Trouble(i));
}
}
}


관련패턴
  • Composite 패턴과 종종 혼용된다. 이 경우, 컴포넌트의 parent가 successor가 된다.

댓글 없음:

댓글 쓰기

블록체인 개요 및 오픈소스 동향

블록체인(block chain) 블록체인은 공공 거래장부이며 가상 화폐로 거래할때 발생할때 발생할 수 있는 해킹을 막는 기술. 분산 데이터베이스의 한 형태로, 지속적으로 성장하는 데이터 기록 리스트로서 분산 노드의 운영자에 의한 임의 조작이 불가...