책임전가패턴 (1)

Creational Patterns ( 생성 패턴 )

These design patterns provides way to create objects while hiding the creation logic, rather than instantiating objects directly using new operator. This gives program more flexibility in deciding which objects need to be created for a given use case. 

생성패턴은 객체의 생성로직을 숨기고 new 명령어를 통하지 않고 객체를 생성하는 방법들을 제공한다. 이는 특정 상황에서 어떤 방법으로 객체를 생성해야할지를 결정하는데 있어서 유연성을 제공한다. 


 Structural Patterns ( 구조적 패턴 )

These design patterns concern class and object composition. Concept of inheritance is used to compose interfaces and define ways to compose objects to obtain new functionalities. 

구조적 패턴들은 클래스와 객체의 구성에 관여한다.

 

 Behavioral Patterns ( 행위적 패턴 )

These design patterns are specifically concerned with communication between objects.

이 패턴들은 객체들 사이의 커뮤니케이션에 관심을 가진다.

 

오늘 살펴볼  Chain of Responsibility (책임 전가 )패턴은 Behavioral 패턴에 속한다.  

책임 전가란 뭐냐? 책임을 다른 놈한테 넘긴다는 말이다. 그게 무슨 말이냐고?

제 조업을 하는 공장을 예로 들어보겠습니다. 이 공장은 자동차를 만듭니다. 자동차를 만드는 과정은 내부에서부터 차근 차근 조립해 나가는 거죠. 차체 바닥을 깔고 그 위에 의자를 올리고 엔진을 끼워넣고 이런식으로 부품(책임)을 계속 조립해 넣습니다. 그러다가 마지막에 완성된 차가 나오게 되는거죠.  

이 글을 읽고있는 독자께서는 맡은 부분이 있겠죠. 예를 들면 바퀴를 끼워넣는 일을 해야한다고 합시다. 그러면 독자님은 그냥 바퀴만 끼우고 나머지는 옆사람한테 넘기면 되는 겁니다. 간단히 말하면 이런 맥락입니다.이해가 되시나요?  

 

Chain of Responsibility Pattern Structure

 

 

A typical object structure might look like this:

일반적인 객체 구조는 아래와 비슷합니다.


         

패턴의 목적 ( Intent ) :  

Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.

이 패턴의 목적은 말이죠, A라는 객체가 요청1을 B객체에 보낼 때 중간에서 이 요청을 핸들링 할 다른 객체들을 두어서 A 와 B 사이의 커플링 관계를 피하기 위함입니다. A 와 B 사이의 각 핸들러들은 자신이 처리할 수 있으면 처리를 하고 처리할 수 없으면 다음 핸들러로 요청을 넘기게 됩니다.


패턴이 나오게 된 동기 ( Motivation ) :

 GoF 의 디자인패턴에서는 애플리케이션에 있는 도움말기능을 예로 듭니다. 도움말( 일반적으로 물음표 )은 컨텍스트별로 다르게 됩니다. 쉽게말하자면 메뉴별로 어떤 메뉴인지에 대한 도움말이 있을 수도 있고 버튼마다 어떤 기능을 실행하는지에 대해서 도움말이 존재하겠죠. 그런데 도움말을 실행할 때 이게 어떤 녀석이 도움말에 대한 정보를 처리해야하는지에 대한 정보는 도움말을 요청하는 객체가 모른다는게 문제라고 합니다. 누가 처리해야하는지도 모르는 것을 어떻게 처리해야하나 고민하다가 나온 패턴이바로 이 책임전가 패턴입니다. 도움말객체가 "A에 대한 도움말 주세요" 라고 chain에 요청을 합니다. 여기서 체인은 핸들러들이 순서대로 연결되어있는 곳입니다. 이 핸들러들 중에서 한놈은 A에 대한 도움말을 주도록 되어있고 또 다른 놈은 B에 대한 도움말을 주도록 되어있는 거죠. 그래서 체인의 시작점으로 요청을 날리면 A에 대한 도움말을 반환하는 핸들러가 나올때까지 옆의 핸들러로 계속 전달합니다. 그러다가 요청을 처리할 수 있는 핸들러를 만나면 요청을 처리하고 결과를 반환하는 거죠. 여기서 중요한 것은 이 체인의 가장 첫 핸들러는 가장 specific한 놈이어야 하고 체인의 제일 끝에 있는 핸들러는 가장 일반적인(공통적인) 놈이어야 한다는 것입니다. 그래서 결국 도움말을 찾지 못하면 일반적인 도움말을 그냥 내보내도록 하는 것이죠. 

 

 

 

유용성 ( Applicability ) :

 

Use Chain of Responsibility when  

책임 전가 패턴은 이럴때 사용하면 됩니다.

    • more than one object may handle a request, and the handler isn't known a priority. The handler should be ascertained automatically. 하나 이상의 객체가 요청을 처리해야 할 때. 그리고 핸들러의 우선순위가 없을 때. 핸들러는 자동적으로 선택되어져야 한다.
       

    • you want to issue a request to one of several objects without specifying the receiver explicitly.
      리시버를 명시하지 않고 여러 객체들 중 하나에 요청을 날리고 싶을 때 

    • the set of objects that can handle a request should be specified dynamically.
      요청을 처리할 수 있는 객체들의 set이 동적으로 지정되어야 할 때 


등장 인물 ( Participants ) :


Handler (HelpHandler)

o defines an interface for handling requests. 요청을 처리하기 위한 인터페이스를 정의한다. 

o (optional) implements the successor link.(선택) successor 링크를 구현한다. 

• ConcreteHandler (PrintButton, PrintDialog)

o handles requests it is responsible for. 책임져야할 부분에 대해서만 요청을 처리한다.
o can access its successor. successor에 접근할 수 있다.
o if the ConcreteHandler can handle the request,it does so; otherwise it forwards the request to its successor.
ConcreteHandler가 처리할 수 있는 요청은 처리를 하지만 그렇지 않은 경우 successor로 요청을 포워딩한다. 

Client

o initiates the request to a ConcreteHandler object on the chain.
체인에 속한 ConcreteHandler 객체로 요청을 날린다. 


원리 ( Collaborations ) :

 

When a client issues a request, the request propagates along the chain until a ConcreteHandler object takes responsibility for handling it.
클라이언트가 요청을 날리면, 그 요청을 처리할 수 있는 ConcreteHandler가 요청을 받고 처리를 할 때 까지 체인을 타고 다른 핸들러로 요청( 핸들러 입장에서는 처리해야할 책임이라고 보면 됩니다 )이 이동합니다. 

 


패턴 사용의 장단점 ( Consequences ): 

 

Chain of Responsibility has the following benefits and liabilities:  


1. Reduced coupling.The pattern frees an object from knowing which other object handles a request. An object only has to know that a request will be handled "appropriately." Both the receiver and the sender have no explicit knowledge of each other, and an object in the chain doesn't have to know about the chain's structure.

As a result, Chain of Responsibility can simplify object inter connections. Instead of objects maintaining references to all candidate receivers, they keep a single reference to their successor.
책임 전가 패턴을 사용하면 커플링을 줄일 수 있습니다. 각 핸들러는 체인의 구조를 알 필요도 없고 단지 다음 핸들러에 대한 reference만 가지고 있다가 요청이 들어왔을 때 자신이 해결 할 수 없는 일이면 다음 핸들러로 요청을 넘기는 일만 하면 되는 것이죠.  

 

2. Added flexibility in assigning responsibilities to objects. Chain of Responsibility gives you added flexibility in distributing responsibilities among objects. You can add or change responsibilities for handling a request by adding to or otherwise changing the chain at run-time. You can combine this with subclassing to specialize handlers statically.  


3. Receipt isn't guaranteed. Since a request has no explicit receiver, there's no guarantee it'll be handledthe request can fall off the end of the chainwithout ever being handled. A request can also go unhandled when thechain is not configured properly.

 

관련 패턴들 : 

 

Chain of Responsibility is often applied in conjunction with Composite. There, a component's parent can act as its successor.책임 전가 패턴은 종종 컴포지트 패턴과 함께 쓰입니다.

 

추가 정보 :   

    • Chain of Responsibility, Command, Mediator, and Observer, address how you can decouple senders and receivers, but with different trade-offs. Chain of Responsibility passes a sender request along a chain of potential receivers. 책임전가, 커맨드, 중재자, 관찰자 패턴은 모두 sender와 receiver사이의 커플링을 줄여주지만 각기 다른 방식을 사용하므로, 디커플링 함으로써 들어가야 하는 비용(단점) 또한 다릅니다.
    • Chain of Responsibility can use Command to represent requests as objects.

 


 

출처 :  http://sourcemaking.com/design_patterns/chain_of_responsibility

Design Patterns : Element of Reusable Object Oriented Software ( by GoF, 1994 )