Chain Of Responsibility Pattern
책임 연쇄 패턴은 메세지를 보내는 객체와 이를 받아 처리하는 객체들 간의 결합도를 없애기 위한 패턴이다. 하나의 요청에 대한 처리가 반드시 한 객체에서만 되지 않고 여러 객체에게 그 처리 기회를 부여하는 동작을 수행한다.
활용성
하나 이상의 객체가 요청을 처리해야 하고 그 요청 처리자중 어떤 것이 선행자인지 모를 때 처리자가 자동으로 확정되어야 할때.
메세지를 받을 객체를 명시하지 않을 채 여러 객체 중 하나에게 처리를 요청하고 싶을 때
요청을 처리할 수 있는 객체 집합이 동적으로 정의되어야 할 때
책임 연쇄 패턴 사용에 따른 결과 객체간 행동적 결합도 저하 다른 객체가 어떻게 요청을 처리하는지 알 필요가 없어진다. 단지 요청을 보내는 객체는 이 메세지가 적절하게 처리될 것이라는 것만 확신하면 된다. 송신측과 수신측 모두 서로를 모르고 또 연결된 객체들조차도 그 연결 구조가 어떻게 되는지 모른다. 그렇기 때문에 객체들간의 상호 작용을 단순화 시킬 수 있다.
객체의 책임할당의 유연성 부여 객체의 책임을 여러 객체로 분산시킬 수 있기 때문에 런타임에 객체 연결고리를 변경하거나 추가하여 책임을 변경하거나 확장할 수 있다.
메세지 수신이 보장되지는 않음 어떤 객체가 이 처리에 대한 수신을 담당한다는 것을 명시하지 않으면 요청이 처리된다는 보장은 없다. 또한 객체들 간의 연결 고리가 잘 정의되어 있지 않다면 요청은 처리되지 못한 채로 버려진다.
책임 연쇄 구조 책임 연쇄의 구조는 다음과 같다.
책임 연쇄의 런타임 구조는 다음과 같다.
C++ 구현 1 2 3 4 5 6 7 8 9 10 11 12 void ChainOfResponsibilityPattern::calculate () { CalculatorHandler* calculatorHandler = new PlusHandler (); calculatorHandler->setNext (new MinusHandler ()); calculatorHandler->setNext (new MultiHandler ()); calculatorHandler->setNext (new DivideHandler ()); calculatorHandler->calculate (5 , 5 , PLUS); calculatorHandler->calculate (5 , 5 , MINUS); calculatorHandler->calculate (5 , 5 , MULTI); calculatorHandler->calculate (5 , 5 , DIVIDE); }
1 2 3 4 5 6 7 enum Operation { PLUS, MINUS, MULTI, DIVIDE, };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class CalculatorHandler { protected : CalculatorHandler* calculatorHandler = nullptr ; Operation op; public : CalculatorHandler (Operation op) : op (op) {} void setNext (CalculatorHandler* calc) { if (calculatorHandler != nullptr ) calculatorHandler->setNext (calc); else calculatorHandler = calc; } virtual void calculate (int n1, int n2, Operation op) = 0 ; };
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 class PlusHandler : public CalculatorHandler{ public : PlusHandler () : CalculatorHandler (PLUS) {} void calculate (int n1, int n2, Operation op) override { if (op == this ->op) std::cout<<n1<<" + " <<n2<<" = " <<n1+n2<<std::endl; else if (this ->calculatorHandler != nullptr ) calculatorHandler->calculate (n1, n2, op); } }; class MinusHandler : public CalculatorHandler{ public : MinusHandler () : CalculatorHandler (MINUS) {} void calculate (int n1, int n2, Operation op) override { if (op == this ->op) std::cout<<n1<<" - " <<n2<<" = " <<n1-n2<<std::endl; else if (this ->calculatorHandler != nullptr ) calculatorHandler->calculate (n1, n2, op); } }; class MultiHandler : public CalculatorHandler{ public : MultiHandler () : CalculatorHandler (MULTI) {} void calculate (int n1, int n2, Operation op) override { if (op == this ->op) std::cout<<n1<<" * " <<n2<<" = " <<n1*n2<<std::endl; else if (this ->calculatorHandler != nullptr ) calculatorHandler->calculate (n1, n2, op); } }; class DivideHandler : public CalculatorHandler{ public : DivideHandler () : CalculatorHandler (DIVIDE) {} void calculate (int n1, int n2, Operation op) override { if (op == this ->op) std::cout<<n1<<" / " <<n2<<" = " <<n1/n2<<std::endl; else if (this ->calculatorHandler != nullptr ) calculatorHandler->calculate (n1, n2, op); } };
java 구현 1 2 3 4 5 6 7 8 9 10 11 12 13 public class Client { public static void main (String[] args) { CalculatorHandler calculatorHandler = new PlusHandler (); calculatorHandler.setNext(new MinusHandler ()); calculatorHandler.setNext(new MultiHandler ()); calculatorHandler.setNext(new DivideHandler ()); calculatorHandler.calculate(5 , 5 , Operation.PLUS); calculatorHandler.calculate(5 , 5 , Operation.MINUS); calculatorHandler.calculate(5 , 5 , Operation.MULTI); calculatorHandler.calculate(5 , 5 , Operation.DIVIDE); } }
1 2 3 4 5 6 public enum Operation { PLUS, MINUS, MULTI, DIVIDE }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public abstract class CalculatorHandler { protected CalculatorHandler calculatorHandler; protected Operation op; public CalculatorHandler (Operation op) { this .op = op; } void setNext (CalculatorHandler calc) { if (Objects.isNull(calculatorHandler)) calculatorHandler = calc; else calculatorHandler.setNext(calc); } abstract void calculate (int n1, int n2, Operation op) ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 public class PlusHandler extends CalculatorHandler { public PlusHandler () { super (Operation.PLUS); } @Override void calculate (int n1, int n2, Operation op) { if (op.equals(this .op)) System.out.printf("%d + %d = %d\n" ,n1, n2, n1 + n2); else if (!Objects.isNull(calculatorHandler)) calculatorHandler.calculate(n1, n2, op); } } public class MinusHandler extends CalculatorHandler { public MinusHandler () { super (Operation.MINUS); } @Override void calculate (int n1, int n2, Operation op) { if (op.equals(this .op)) System.out.printf("%d - %d = %d\n" ,n1, n2, n1 - n2); else if (!Objects.isNull(calculatorHandler)) calculatorHandler.calculate(n1, n2, op); } } public class MultiHandler extends CalculatorHandler { public MultiHandler () { super (Operation.MULTI); } @Override void calculate (int n1, int n2, Operation op) { if (op.equals(this .op)) System.out.printf("%d * %d = %d\n" ,n1, n2, n1 * n2); else if (!Objects.isNull(calculatorHandler)) calculatorHandler.calculate(n1, n2, op); } } public class DivideHandler extends CalculatorHandler { public DivideHandler () { super (Operation.DIVIDE); } @Override void calculate (int n1, int n2, Operation op) { if (op.equals(this .op)) System.out.printf("%d / %d = %d\n" ,n1, n2, n1 / n2); else if (!Objects.isNull(calculatorHandler)) calculatorHandler.calculate(n1, n2, op); } }