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 handledโ€”the 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 )