13.    The Chain of Responsibility Pattern

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

 

구조

사용자 삽입 이미지

 

역할

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

 

의도

어떤request에 대해서 한 개 이상의 오브젝트에게 처리할 기회를 줌으로써,requestsenderreceiverdecoupling한다. Receiver가 될 수 있는 오브젝트들을 연결하여 체인을 만들고, request가 처리될 때 까지 체인을 따라 전달한다.

 

적용시기

결론

l        이 패턴의1차적인 목적은 다른 패턴들처럼 객체 간의 의존성을 약화시키는 것이다.따라서 하나의 객체는 다른 객체에게 요청 내용을 전달하는 방법만 파악해 두면 된다.

l        체인 안의 각각의 자바 객체는 자체적으로 내장되어 있다.각 객체들은 다른 객체에 대한 정보는 전혀 없고,자신이 요청 내용을 충족시킬 수 있는지의 여부를 결정할 수 있는 능력만 보유하면 된다.이런 점은 각각의 객체를 작성하는 일뿐만 아니라 체인을 생성하는 작업을 매우 쉽게 한다.

l        개발자는 체인 안에서 마지막 객체가 전달한 모든 요청 내용을 처리할 수 있는지 또는 해당 요청 사항을 단지 무시해 버리는지를 판단할 수 있다.그러나 이와 같은 작업을 효율적으로 수행하려면,개발자가 해당 체인의 마지막 객체가 어느 객체인지 파악하고 있어야 한다.

l        마지막으로 자바 언어는 다중 상속을 허용하지 않으므로 기본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() {

       Supportalice  = 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));

       }

       

   }

}

 

관련패턴

l        Composite패턴과 종종 혼용된다.이 경우,컴포넌트의parentsuccessor가 된다.

 

'Programming > Design Pattern' 카테고리의 다른 글

[펌] The Flyweight Pattern  (0) 2006.01.21
[펌] Chapter 5 Behavioral Patterns(행위 패턴)  (0) 2006.01.21
[펌] The Command Pattern  (0) 2006.01.21
[펌] The Facade Pattern  (0) 2006.01.21
[펌] The Flyweight Pattern  (0) 2006.01.21

Posted by 영웅기삼
,