프로그래밍/자바 디자인패턴

디자인패턴 Chain of Responsibility 패턴

가카리 2012. 8. 2. 19:53
반응형

 

 

책임의 사슬 패턴

 

핸드폰이 고장나면 일단 구매처에 물어보고 구매처는 as센터로 가라고 하고 as센터에서는 이건 못고친다고 하면서 용산 전문 수리점으로 가라고 한다.

 

이렇게 책임 떠넘기기를 디자인패턴으로 표현했다.

 

Trouble 클래스

 

package kch;

 

public class Trouble {

        //발생한 트러블을 표현하는 클래스

        /**

         * @uml.property  name="number"

         */

        private int number;//트러블 번호

       

        public Trouble(int number){

               this.number = number;//트러블의 생성

        }

       

        /**

         * @return

         * @uml.property  name="number"

         */

        public int getNumber(){

               return number;//트러블 번호를 얻는다.

        }

 

        public String toString(){

               return  "[Trouble " + number +"]";//트러블의 문자열 표현

        }

}

 

 

Support 클래스

 

package kch;

 

public abstract class Support {

        /**

         * @uml.property  name="name"

         */

        private String name;//트러블 해결자의 이름

        /**

         * @uml.property  name="next"

         * @uml.associationEnd 

         */

        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){//트러블이 해결 안됬지만 아직 남은 support 있다면

              

                       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.");

        }

 

}

 

 

NoSupport 클래스

 

package kch;

 

public class NoSupport extends Support{

 

        //이 클래스는 문제를 해결 못하는 클래스입니다.

        public NoSupport(String name) {

               super(name);

               // TODO Auto-generated constructor stub

        }

 

        @Override

        protected boolean resolve(Trouble trouble) {

               // TODO Auto-generated method stub

               return false;//무조건 해결 못함

        }

 

}

 

LimitSupport 클래스

 

package kch;

 

public class LimitSupport extends Support{

        /**

         * @uml.property  name="limit"

         */

        private int limit;

       

        public LimitSupport(String name, int limit){//생성자

               super(name);

               this.limit = limit;

        }

 

        @Override

        protected boolean resolve(Trouble trouble) {//해결용 메소드

               //limit 설정하고 이 값보다 미만이면 해결을 할 수 있다.

               // TODO Auto-generated method stub

               if(trouble.getNumber() < limit){

                       return true;

               }else{

                       return false;                

               }

        }

}

 

 

OddSupport 클래스

 

package kch;

 

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;

              

               }

        }

}

 

SpecialSupport 클래스

 

package kch;

 

public class SpecialSupport extends Support{

 

        /**

         * @uml.property  name="number"

         */

        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;

              

               }

        }

}

 

Main 클래스

 

package kch;

 

public class Main {

        public static void main(String[] args){

               Support alice = new NoSupport("Alice");

               Support bob = new LimitSupport("Bob", 100);

               Support charlie = new SpecialSupport("Charle", 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);

               //트러블은 NoSupport -> LimitSupport 100 -> SpecialSupport 429

               // -> LimitSupport 200 -> OddSupport  -> LimitSupport 300

               //순으로 처리를 시도한다. 여기가 책임 떠넘기기 부분

              

               //다양한 트러블 발생

               for(int i = 0 ; i < 500 ; i += 33){

              

                       alice.support(new Trouble(i));//트러블을 발생시킨다.

                       //support함수에서 추상메소드인 resolve 실행하게 되는데

                       //이때 각 인스턴스에 따라서 다르게 실행이 된다.

                       //      if(resolve(trouble)){//트러블이 해결되면

                       //      done(trouble);//끝남

                       //}else if(next != null){//트러블이 해결 안됬지만 아직 남은 support 있다면

                       //      next.support(trouble);//해결 못햇음

                       // 위에서 support메소드가 재귀적 구성으로 되있으므로 위에 setNext한 순서대로 실행이된다.

                      

               }

        }

 

}

 

 

 

이 패턴의 장점은 언제든지 main에서 요구를 처리하는 순서를 바꿀 수 있습니다.

이 요구는 이 사람이 처리하게 하라면 프로그램 실행 중에 처리자를 변경하기 어렵습니다.

 

또한 각자 처리할 수 있는 부분만 처리 하기 때문에 임무의 분배가 편해집니다. 자기가 할 수 있는 것만 하기 때문입니다.

 

 

반응형