๐Ÿ’ป Programming/GoF Design Pattern (23)

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.

์ด ํŒจํ„ด๋“ค์€ ๊ฐ์ฒด๋“ค ์‚ฌ์ด์˜ ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜์— ๊ด€์‹ฌ์„ ๊ฐ€์ง„๋‹ค.

 

์˜ค๋Š˜ ์‚ดํŽด๋ณผ  Memento ํŒจํ„ด์€ Behavioral ํŒจํ„ด์— ์†ํ•ฉ๋‹ˆ๋‹ค. 

 

Memento Pattern Structure

 




  

ํŒจํ„ด์˜ ๋ชฉ์  ( Intent ) :  

Without violating encapsulation, capture and externalize an object's internal state so that the object can be restored to this state later.


ํŒจํ„ด์ด ๋‚˜์˜ค๊ฒŒ ๋œ ๋™๊ธฐ ( Motivation ) :

    ๋‹ค์ด์–ด๊ทธ๋žจ์„ ๊ทธ๋ฆฌ๋Š” ํˆด์„ ์˜ˆ๋กœ ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์‚ฌ๊ฐํ˜• ๋‘๊ฐœ๋ฅผ ๊ทธ๋ฆฌ๊ณ  ๋‘ ์‚ฌ๊ฐํ˜•์„ ์„ ์œผ๋กœ ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค. ์ž ์ด์ œ ์•„๋ž˜์ชฝ ์‚ฌ๊ฐํ˜•์„ ์˜ค๋ฅธ์ชฝ์œผ๋กœ ์ด๋™์‹œํ‚ต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์•„๋ž˜ ๊ทธ๋ฆผ์ฒ˜๋Ÿผ ๋‘ ์‚ฌ๊ฐํ˜•์„ ์ด์€ ์„ ๋„ ๋”ฐ๋ผ์„œ ์ด๋™ํ•˜๋ฉด์„œ ๋‘ ์‚ฌ๊ฐํ˜•์„ ๊ณ„์† ์ด์–ด์ค๋‹ˆ๋‹ค.  


์ด๋ ‡๊ฒŒ ๋‘ ๊ฐ์ฒด ์‚ฌ์ด์˜ ์—ฐ๊ฒฐ ๊ด€๊ณ„๋ฅผ ์œ ์ง€์‹œํ‚ค๋Š” ์ž˜ ์•Œ๋ ค์ง„ ๋ฐฉ๋ฒ•์ค‘ ํ•˜๋‚˜๋Š” ์ œ์•ฝ-ํ•ด๊ฒฐ ์‹œ์Šคํ…œ(constraint-solving system)์ž…๋‹ˆ๋‹ค. ์ด ์‹œ์Šคํ…œ์€ ConstraintSolver ์— ์บก์Šํ™”๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ConstraintSolver๋Š” ๊ฐ์ฒด๋“ค ์‚ฌ์ด์˜ ์—ฐ๊ฒฐ์„ ๊ธฐ๋กํ•˜๊ณ  ์ด ์—ฐ๊ฒฐ์„ ์„ค๋ช…ํ•˜๋Š” ์ˆ˜ํ•™์‹์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊ฐ์ฒด์˜ ์œ„์น˜๊ฐ€ ๋ณ€๊ฒฝ์ด ๋˜๋ฉด ์ด ์ˆ˜ํ•™์‹์„ ๋‹ค์‹œ ๊ณ„์‚ฐํ•˜์—ฌ ์„ ์„ ์–ด๋–ป๊ฒŒ ๊ทธ๋ ค์•ผ ํ•˜๋Š”์ง€๋ฅผ ์•Œ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

ํ•˜ ์ง€๋งŒ ๋˜๋Œ๋ฆฌ๊ธฐ ๊ธฐ๋Šฅ์€ ์ƒ๊ฐ์ฒ˜๋Ÿผ ์‰ฝ์ง€๊ฐ€ ์•Š์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์‚ฌ๊ฐํ˜•์ด ์›€์ง์ธ ๊ฑฐ๋ฆฌ๋ฅผ ๊ณ„์‚ฐํ•˜์—ฌ ๊ทธ๋งŒํผ ๋‹ค์‹œ ๋˜๋Œ๋ฆฐ๋‹ค๊ณ  ํ–ˆ์„ ๋•Œ ๊ณผ์—ฐ ๋‘ ์‚ฌ๊ฐํ˜•์„ ์—ฐ๊ฒฐํ•˜๋Š” ์„ ์€ ์–ด๋–ป๊ฒŒ ์›€์ง์—ฌ์•ผ ํ•˜๋Š”๊ฐ€๋ฅผ ์ƒ๊ฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ๋ถˆ์™„์ „ํ•œ ๋˜๋Œ๋ฆฌ๊ธฐ๊ฐ€ ๋˜์–ด๋ฒ„๋ฆด ํ…Œ๋‹ˆ๊นŒ์š”.

 

์ผ ๋ฐ˜์ ์œผ๋กœ ConstraintSolver์˜ public interface ๋Š” undo๊ธฐ๋Šฅ์„ ์™„์ „ํžˆ ๊ตฌํ˜„ํ•˜๊ธฐ์— ๋ถˆ์ถฉ๋ถ„ํ•ฉ๋‹ˆ๋‹ค. undo ๋ฉ”์นด๋‹ˆ์ฆ˜์€ ์ด์ „์˜ ์ƒํƒœ๋ฅผ ๋‹ค์‹œ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ์œ„ํ•ด์„œ ConstraintSolver์™€ ์ข€ ๋” ๋ฐ€์ ‘ํ•œ ๊ด€๊ณ„๋ฅผ ๋งบ์–ด์•ผ ํ•˜์ง€๋งŒ ํ•œํŽธ์œผ๋กœ๋Š” ConstraintSolver์˜ ๋‚ด๋ถ€๋ฅผ ๋…ธ์ถœ์‹œํ‚ค๋ฉด ์•ˆ๋ฉ๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋ฅผ ํ’€๊ธฐ์œ„ํ•ด์„œ ๋‚˜์˜จ ํŒจํ„ด์ด ๋ฐ”๋กœ ๋ฉ”๋ฉ˜ํ†  ํŒจํ„ด์ž…๋‹ˆ๋‹ค. ๋ฉ”๋ฉ˜ํ† ๋Š” ๋‹ค๋ฅธ ๊ฐ์ฒด(๋ฉ”๋ฉ˜ํ† ์˜ originator)์˜ ๋‚ด๋ถ€ ์ƒํƒœ๋ฅผ ์ €์žฅํ•˜๋Š” ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค. undo ๋ฉ”ํƒ€๋‹ˆ์ฆ˜์€ originator์˜ ์ด์ „ ์ƒํƒœ๊ฐ€ ํ•„์š”ํ•  ๋•Œ ๋ฉ”๋ฉ˜ํ† ๋ฅผ ์š”์ฒญํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. originator๋Š” ์ž์‹ ์˜ ํ˜„์žฌ ์ƒํƒœ๋ฅผ ๋ฉ”๋ฉ˜ํ† ์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์˜ค๋กœ์ง€ originator๋งŒ์ด ๋ฉ”๋ฉ˜ํ† ์— ์ €์žฅํ•œ ์ž์‹ ์˜ ์ƒํƒœ๋ฅผ ์ €์žฅ ๋˜๋Š” ์ฝ์–ด์˜ฌ ์ˆ˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค โ€” ๋ฉ”๋ฉ˜ํ† ๋Š” ๋‹ค๋ฅธ ๊ฐ์ฒด๋“ค์—๊ฒŒ "์˜คํŒŒํฌ(์นจํˆฌํ•  ์ˆ˜ ์—†๋Š” ๊ฒƒ)"๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ์ฃ . ์œ„์—์„œ ์˜ˆ๋กœ ๋“  ํˆด์—์„œ ConstraintSolver๋Š” originator์˜ ์—ญํ• ์„ ํ•˜๋Š”๊ฑฐ์ฃ .  

 

The following sequence of events characterizes theundo process:

      1. The editor requests a memento from the ConstraintSolver as aside-effect of the move operation.

      2. The ConstraintSolver creates and returns a memento, an instance of a class SolverState in this case. A SolverState memento contains data structures that describe the current state of the ConstraintSolver's internal equations and variables.

      3. Later when the user undoes the move operation, the editor gives the SolverState back to the ConstraintSolver.

      4. Based on the information in the SolverState, the ConstraintSolver changes its internal structures to return its equations and variables to their exact previous state.

This arrangement lets the ConstraintSolver entrust other objects with the information it needs to revert to a previous state without exposing its internal structure and representations.



์œ ์šฉ์„ฑ ( Applicability ) :

 

Use the Memento pattern when

    • a snapshot of (some portion of) an object's state must be saved so that it can be restored to that state later, and

    • a direct interface to obtaining the state would expose implementation details and break the object's encapsulation.



๋“ฑ์žฅ ์ธ๋ฌผ ( Participants ) :


โ€ข Memento (SolverState)

o stores internal state of the Originator object. The memento may store as much or as little of the originator's internal state as necessary at its originator's discretion.
o protects against access by objects other than the originator. Mementos have effectively two interfaces. Caretaker sees a narrow interface to the Mementoโ€”it can only pass the memento to other objects. Originator, in contrast, sees a wide interface, one that lets it access all the data necessary to restore itself to its previous state. Ideally, only the originator that produced the memento would be permitted to access the memento's internal state.

โ€ข Originator (ConstraintSolver)

o creates a memento containing a snapshot of its current internal state.
o uses the memento to restore its internal state.

โ€ข Caretaker (undo mechanism)

o is responsible for the memento's safekeeping.
o never operates on or examines the contents of a memento.

 

 

์›๋ฆฌ ( Collaborations ) :  

โ€ข A caretaker requests a memento from an originator, holds it for a time, and passes it back to the originator, as the following interaction diagram illustrates:   



 

 

Sometimes the caretaker won't pass the memento back to the originator, because the originator might never need to revert to an earlier state.

โ€ข Mementos are passive. Only the originator that created a memento will assign or retrieve its state.

 


ํŒจํ„ด ์‚ฌ์šฉ๋ฒ•

    1. Identify the roles of โ€œcaretakerโ€ and โ€œoriginatorโ€.
    2. Create a Memento class and declare the originator a friend.
    3. Caretaker knows when to "check point" the originator.
    4. Originator creates a Memento and copies its state to that Memento.
    5. Caretaker holds on to (but cannot peek into) the Memento.
    6. Caretaker knows when to "roll back" the originator.
    7. Originator reinstates itself using the saved state in the Memento.

ํŒจํ„ด ์‚ฌ์šฉ์˜ ์žฅ๋‹จ์  ( Consequences ): 

The Memento pattern has several consequences:

 

    1. Preserving encapsulation boundaries. Memento avoids exposing information that only an originator should manage but that must be stored nevertheless outside the originator. The pattern shields other objects from potentially complex Originator internals, thereby preserving encapsulation boundaries.

    2. It simplifies Originator. In other encapsulation-preserving designs, Originator keeps the versions of internal state that clients have requested. That puts all the storage management burden on Originator. Having clients manage the state they ask for simplifies Originator and keeps clients from having to notify originators when they're done.

    3. Using mementos might be expensive. Mementos might incur considerable overhead if Originator must copy large amounts of information to store in the memento or if clients create and return mementos to the originator often enough. Unless encapsulating and restoring Originator state is cheap, the pattern might not be appropriate.

    4. Defining narrow and wide interfaces. It may be difficult in some languages to ensure that only the originator can access the memento's state.

    5. Hidden costs incaring for mementos. A caretaker is responsible for deleting the mementos it cares for. However, the caretaker has no idea how much state is in the memento. Hence an otherwise lightweight caretaker might incur large storagecosts when it stores mementos.


๊ด€๋ จ ํŒจํ„ด๋“ค :  

 

Command : Commands can use mementos to maintain state for undoable operations.  

Iterator : Mementos can be used for iteration as described earlier.



์ถ”๊ฐ€ ์ •๋ณด :       

    • Command and Memento act as magic tokens to be passed around and invoked at a later time. In Command, the token represents a request; in Memento, it represents the internal state of an object at a particular time. Polymorphism is important to Command, but not to Memento because its interface is so narrow that a memento can only be passed as a value.
    • Command can use Memento to maintain the state required for an undo operation.
    • Memento is often used in conjunction with Iterator. An Iterator can use a Memento to capture the state of an iteration. The Iterator stores the Memento internally.

 

 


 

์ถœ์ฒ˜ :  http://sourcemaking.com/design_patterns/memento

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

 


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.

์ด ํŒจํ„ด๋“ค์€ ๊ฐ์ฒด๋“ค ์‚ฌ์ด์˜ ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜์— ๊ด€์‹ฌ์„ ๊ฐ€์ง„๋‹ค.

 

์˜ค๋Š˜ ์‚ดํŽด๋ณผ  Interpreter ํŒจํ„ด์€ Behavioral ํŒจํ„ด์— ์†ํ•ฉ๋‹ˆ๋‹ค. 

 

Interpreter Pattern Structure

 



  

ํŒจํ„ด์˜ ๋ชฉ์  ( Intent ) :  

Given a language, define a represention for its grammar along with an interpreter that uses the representation to interpret sentences in the language.


ํŒจํ„ด์ด ๋‚˜์˜ค๊ฒŒ ๋œ ๋™๊ธฐ ( Motivation ) :

   
A class of problems occurs repeatedly in a well-defined and well-understood domain. If the domain were characterized with a "language", then problems could be easily solved with an interpretation "engine".

 

GoF์˜ ๋””์ž์ธ ํŒจํ„ด์—์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ ์˜ˆ์ œ๊ฐ€ ๋‚˜์˜ต๋‹ˆ๋‹ค.

 

์•„๋ž˜ ๋ฌธ๋ฒ•์ด ์ •๊ทœ์‹์„ ํ‘œํ˜„ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค.

expression ::= literal | alternation | sequence | repetition |
                   '(' expression ')'

alternation ::= expression '|' expression
sequence ::= expression '&' expression
repetition ::= expression '*'
literal ::= 'a' | 'b' | 'c' | ... { 'a' | 'b' | 'c' | ... }*  


์—ฌ๊ธฐ์„œ expression์€ ์‹œ์ž‘ symbol์ด๊ณ  literal์€ ์ข…๋ฃŒ symbol์ž…๋‹ˆ๋‹ค. 

์ธํ„ฐํ”„๋ฆฌํ„ฐ ํŒจํ„ด์€ ๊ฐ ๋ฌธ๋ฒ•์„ ํ‘œํ˜„ํ•˜๊ธฐ ์œ„ํ•ด์„œ ํ•˜๋‚˜์˜ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์šฐ์ธก์˜ ์‹ฌ๋ณผ๋“ค์€ ์ด ํด๋ž˜์Šค๋“ค์˜ ์ธ์Šคํ„ด์Šค์ž…๋‹ˆ๋‹ค. ์œ„ ๋ฌธ๋ฒ•์€ ๋‹ค์„ฏ๊ฐœ์˜ ํด๋ž˜์Šค๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ์Šต๋‹ˆ๋‹ค. ์ถ”์ƒํด๋ž˜์Šค RegularExpression ๊ณผ ๊ทธ ํ•˜์œ„ ํด๋ž˜์Šค๋“ค์ธ LiteralExpression, AlternationExpression, SequenceExpression, ๊ทธ๋ฆฌ๊ณ  RepetitionExpression์ž…๋‹ˆ๋‹ค. ๋งˆ์ง€๋ง‰์˜ ์„ธ ํด๋ž˜์Šค๋“ค์€ ํ•˜์œ„ํ‘œํ˜„์‹์„ ๊ฐ–๋Š” ๋ณ€์ˆ˜๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.


 

์ด ๋ฌธ๋ฒ•์œผ๋กœ ์ •์˜๋œ ๋ชจ๋“  ์ •๊ทœ ํ‘œํ˜„์‹์€ ์œ„์™€๊ฐ™์€ ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค๋กœ ์ด๋ฃจ์–ด์ง„ ์ถ”์ƒ ๋ฌธ๋ฒ• ํŠธ๋ฆฌ๋กœ ํ‘œํ˜„๋ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค๋ฉด, ์ถ”์ƒ ๋ฌธ๋ฒ• ํŠธ๋ฆฌ๋Š” ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.


 

represents the regular expression  

raining & (dogs | cats) *

We can create an interpreter for these regular expressions by definingthe Interpret operation on each subclass of RegularExpression.Interpret takes as an argument the context in which to interpret theexpression. The context contains the input string and information onhow much of it has been matched so far. Each subclass ofRegularExpression implements Interpret to match the next part of theinput string based on the current context. For example,

  • LiteralExpression will check if the input matches the literal it defines,

  • AlternationExpression will check if the input matches any of its alternatives,

  • RepetitionExpression will check if the input has multiple copies of expression it repeats, and so on.

 

์œ ์šฉ์„ฑ ( Applicability ) :

 

Use the Interpreter pattern when there is a language to interpret, and you can represent statements in the language as abstract syntax trees.The Interpreter pattern works best when

 

  • the grammar is simple. For complex grammars, the class hierarchy forthe grammar becomes large and unmanageable. Tools such as parsergenerators are a better alternative in such cases. They can interpret expressions without building abstract syntax trees, which can savespace and possibly time.

  • efficiency is not a critical concern. The most efficient interpreters are usually not implemented by interpreting parse trees directly but by first translating them into another form. For example, regular expressions are often transformed into state machines. But even then,the translator can be implemented by the Interpreter pattern, so the pattern is still applicable.

๋“ฑ์žฅ ์ธ๋ฌผ ( Participants ) :

  • AbstractExpression (RegularExpression)
    o
    declaresanabstractInterpretoperationthatiscommontoallnodes in the abstract syntax tree.
  • TerminalExpression (LiteralExpression)
    o
    implements an Interpret operation associated with terminal symbols in the grammar.
    o
    an instance is required for every terminal symbol in a sentence.

  • NonterminalExpression (AlternationExpression,RepetitionExpression, SequenceExpressions)
    o
    one such class is required for every rule R ::= R1 R2 ... Rn in the grammar.
    o
    maintains instance variables of type AbstractExpression for each of the symbols R1 through Rn.
    o
    implements an Interpret operation for nonterminal symbols in the grammar. Interpret typically calls itself recursively on the variables representing R1 through Rn.

  • Context
    o
    contains information that's global to the interpreter.

  • Client
    o
    builds (or is given) an abstract syntax tree representing a particular sentence in the language that the grammar defines. The abstract syntax tree is assembled from instances of the NonterminalExpression and TerminalExpression classes.
    o
    invokes the Interpret operation.


์›๋ฆฌ ( Collaborations ) :  

  • The client builds (or is given) the sentence as an abstract syntax tree of NonterminalExpression and TerminalExpression instances. Then the client initializes the context and invokes the Interpret operation.

  • Each NonterminalExpression node defines Interpret in terms ofInterpret on each subexpression. The Interpret operation of eachTerminalExpression defines the base case in the recursion.

  • The Interpret operations at each node use the context to store and access the state of the interpreter.

ํŒจํ„ด ์‚ฌ์šฉ๋ฒ•

  1. Decide if a "little language" offers a justifiable return on investment.
  2. Define a grammar for the language.
  3. Map each production in the grammar to a class.
  4. Organize the suite of classes into the structure of the Composite pattern.
  5. Define an interpret(Context) method in the Composite hierarchy.
  6. The Context object encapsulates the current state of the input and output as the former is parsed and the latter is accumulated. It is manipulated by each grammar class as the "interpreting" process transforms the input into the output.
ํŒจํ„ด ์‚ฌ์šฉ์˜ ์žฅ๋‹จ์  ( Consequences ): 

  1. The Interpreter pattern has the following benefits and liabilities:  


  2. 1. It's easy to change and extend the grammar. Because the pattern uses classes to represent grammar rules, you canuse inheritance to change or extend the grammar. Existing expressions can be modified incrementally, and new expressions can be defined as variations on old ones.  


  3. 2. Implementing the grammar is easy,too. Classes defining nodes in the abstract syntax tree have similar implementations. These classes are easy to write, and often their generation can be automated with a compiler or parser generator.  


  4. 3. Complex grammars are hard to maintain. The Interpreter pattern defines at least one class for every rule in the grammar (grammar rules defined using BNF may require multiple classes). Hence grammars containing many rules can be hard to manage and maintain. Other design patterns can be applied to mitigate the problem (see Implementation).But when the grammar is very complex, other techniques such as parser or compiler generators are more appropriate.  


  5. 4. Adding new ways to interpret expressions. The Interpreter pattern makes it easier to evaluate an expression in a new way. For example, you can support pretty printing ortype-checking an expression by defining a new operation on the expression classes. If you keep creating new ways of interpreting an expression, then consider using the Visitor pattern to avoid changing the grammar classes.

 

๊ด€๋ จ ํŒจํ„ด๋“ค :  

 

Composite :The abstract syntax tree is an instance of the Composite pattern.

Flyweight shows how to share terminal symbols within the abstract syntax tree.

Iterator :The interpreter can use an Iterator to traverse the structure.

Visitor can be used to maintain the behavior in each node in the abstract syntax tree in one class.

 

์ถ”๊ฐ€ ์ •๋ณด :    
  • Considered in its most general form (i.e. an operation distributed over a class hierarchy based on the Composite pattern), nearly every use of the Composite pattern will also contain the Interpreter pattern. But the Interpreter pattern should be reserved for those cases in which you want to think of this class hierarchy as defining a language.
  • Interpreter can use State to define parsing contexts.
  • The abstract syntax tree of Interpreter is a Composite (therefore Iterator and Visitor are also applicable).
  • Terminal symbols within Interpreter's abstract syntax tree can be shared with Flyweight.
  • The pattern doesn't address parsing. When the grammar is very complex, other techniques (such as a parser) are more appropriate.
 

์ถœ์ฒ˜ :  http://sourcemaking.com/design_patterns/interpreter

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


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.

์ด ํŒจํ„ด๋“ค์€ ๊ฐ์ฒด๋“ค ์‚ฌ์ด์˜ ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜์— ๊ด€์‹ฌ์„ ๊ฐ€์ง„๋‹ค.

 

์˜ค๋Š˜ ์‚ดํŽด๋ณผ  Observer ํŒจํ„ด์€ Behavioral ํŒจํ„ด์— ์†ํ•ฉ๋‹ˆ๋‹ค. 

์˜ต์ €๋ฒ„๋ผ๊ณ  ํ•˜๋‹ˆ๊นŒ 10๋…„์ „์— ์Šคํƒ€ํฌ๋ž˜ํ”„ํŠธ์—์„œ ๋‚˜์™”๋˜ ์˜ต์ €๋ฒ„๊ฐ€ ์ƒ๊ฐ์ด ๋‚˜๋„ค์š”. cloaking์ƒํƒœ๋กœ ์—ฌ๊ธฐ์ €๊ธฐ ๋งต์„ ๋’ค์ง€๊ณ  ๋‹ค๋…”๋˜ ๋…€์„์ด์ฃ . HP๋Š” ์–ด์ฐŒ๋‚˜ ์ ์€์ง€ ํ•œ๋ฐฉ์— ๊ทธ๋ƒฅ ํŽ‘ ํ„ฐ์ ธ์„œ ์ฃฝ์–ด๋ฒ„๋ฆฌ๋˜ ๋…€์„์ด์—ˆ์ฃ  ใ…Žใ…Ž.

์ด ์˜ต์ €๋ฒ„ ํŒจํ„ด์€ ํ•œ ๊ฐ์ฒด์˜ ์ƒํƒœ๋ฅผ ์ง€์ผœ๋ณด๊ณ  ์žˆ๋‹ค๊ฐ€ ์ด ๊ฐ์ฒด์˜ ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ์ด ๋˜๋ฉด ์ด ๊ฐ์ฒด์˜ ์ƒํƒœ์— ์˜์กด์ ์ธ ๋‹ค๋ฅธ ๊ฐ์ฒด๋“ค์˜ ์ƒํƒœ๋ฅผ ์ž๋™์œผ๋กœ ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ๊ฒŒ๋” ํ•ด์ฃผ๋Š” ํŒจํ„ด์ด๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.  

์•„๋ž˜์—์„œ ์ข€ ๋” ์ž์„ธํžˆ ์•Œ์•„๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.


Observer Pattern Structure

 




  

ํŒจํ„ด์˜ ๋ชฉ์  ( Intent ) :  

Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.

์˜ต ์ €๋ฒ„ ํŒจํ„ด์˜ ๋ชฉ์ ์€ ํ•˜๋‚˜์˜ ๊ฐ์ฒด์— ์—ฌ๋Ÿฌ๊ฐœ์˜ ๊ฐ์ฒด๊ฐ€ ์˜์กด์ ์ธ ๊ฒฝ์šฐ์—, ๊ทธ ํ•œ ๊ฐ์ฒด์˜ ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ์ด ๋˜๋ฉด ์ด ๊ฐ์ฒด์— ์˜์กด์ ์ธ ๋‹ค๋ฅธ ์—ฌ๋Ÿฌ๊ฐœ์˜ ๊ฐ์ฒด๋“ค์ด notification์„ ๋ฐ›๊ณ  ์ž๋™์œผ๋กœ ์ž์‹ ๋“ค์˜ ์ƒํƒœ๋ฅผ ์—…๋ฐ์ดํŠธ๋ฅผ ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๊ธฐ ์œ„ํ•จ์ž…๋‹ˆ๋‹ค.


ํŒจํ„ด์ด ๋‚˜์˜ค๊ฒŒ ๋œ ๋™๊ธฐ ( Motivation ) :

     

Both a spreadsheet object and bar chart object can depict information in the same application data object using different presentations. The spreadsheet and the bar chart don't know about each other, thereby letting you reuse only the one you need. But they behave as though they do. When the user changes the information in the spreadsheet, the bar chart reflects the changes immediately, and vice versa.





This behavior implies that the spreadsheet and bar chart are dependent on the data object and therefore should be notified of any change in its state. And there's no reason to limit the number of dependent objects to two; there may be any number of different user interfaces to the same data.  


The Observer pattern describes how to establish these relationships. The key objects in this pattern are subject and observer. A subject may have any number of dependent observers. All observers are notified whenever the subject undergoes a change in state. In response, each observer will query the subject to synchronize its state with the subject's state.  


This kind of interaction is also known as publish-subscribe. The subject is the publisher of notifications. It sends out these notifications without having to know who its observers are. Any number of observers can subscribe to receive notifications.  

 


์œ ์šฉ์„ฑ ( Applicability ) :

 

Use the Observer pattern in any of the following situations:  

 

    • When an abstraction has two aspects, one dependent on the other. Encapsulating these aspects in separate objects lets you vary and reuse them independently.
    • When a change to one object requires changing others, and you don't know how many objects need to be changed.
    • When an object should be able to notify other objects without making assumptions about who these objects are. In other words, you don't want these objects tightly coupled.

 



๋“ฑ์žฅ ์ธ๋ฌผ ( Participants ) :


Subject

o knows its observers. Any number of Observer objects may observe a subject.

o provides an interface for attaching and detaching Observer objects.

Observer

o defines an updating interface for objects that should be notified of changes in a subject. 

ConcreteSubject ( ์ดํ•˜ CS ) 

o stores state of interest to ConcreteObserver objects. 

o sends a notification to its observers when its state changes.

ConcreteObserver ( ์ดํ•˜ CO ) 

o maintains a reference to a ConcreteSubject object.

o stores state that should stay consistent with the subject's.  

o implements the Observer updating interface to keep its state consistent with the subject's.

 

 

์›๋ฆฌ ( Collaborations ) :  

  • ConcreteSubject notifies its observers whenever a change occurs that could make its observers' state inconsistent with its own.
    ConcreteSubject( ์ดํ•˜ CS )๊ฐ์ฒด๊ฐ€ ์ด ๊ฐ์ฒด๋ฅผ ์ง€์ผœ๋ณด๋Š” ์˜ต์ €๋ฒ„๋“ค์—๊ฒŒ ์ž์‹ ์˜ ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๋ ค์ค๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์˜ต์ €๋ฒ„๋“ค์€ ์ด ์ƒํƒœ๋ฅผ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. CS๊ฐ์ฒด๊ฐ€ ์ž์‹ ์˜ ์ƒํƒœ๋ณ€ํ™”๋ฅผ ์•Œ๋ ค์ค„ ๋•Œ๋งˆ๋‹ค ์˜ต์ €๋ฒ„๋“ค ๋˜ํ•œ ์ƒํƒœ์ •๋ณด๋ฅผ ์—…๋ฐ์ดํŠธ ํ•˜๊ฒŒ ๋˜๋Š” ๊ฑฐ์ฃ .
  • After being informed of a change in the concrete subject, a ConcreteObserver object may query the subject for information. ConcreteObserver uses this information to reconcile its state with that of the subject.
    CS ๊ฐ€ ๋ณด๋‚ธ ์ƒํƒœ์ •๋ณด๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ๋‹ค๋Š” ์•Œ๋ฆผ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›์€ ConcreteObserver( ์ดํ•˜ CO )๋Š” CS์˜ ์ƒํƒœ์ •๋ณด๋ฅผ ์–ป๊ธฐ์œ„ํ•ด getState()๋ฅผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. CO๋Š” ์ด๋ ‡๊ฒŒ ์–ป์€ ์ •๋ณด๋ฅผ ์ด์šฉํ•ด์„œ CS ์ƒํƒœ์™€ ์ž์‹ ์ด ๊ฐ–๊ณ  ์žˆ๋Š” ์ƒํƒœ์ •๋ณด๋ฅผ ๋™์ผํ•˜๊ฒŒ ๋™๊ธฐํ™”์‹œํ‚ต๋‹ˆ๋‹ค.

    The following interaction diagram illustrates the collaborations between a subject and two observers:

 


Note how the Observer object that initiates the change request postpones its update until it gets a notification from the subject. Notify is not always called by the subject. It can be called by an observer or by another kind of object entirely. ์˜ต์ €๋ฒ„๊ฐ€ ๊ด€์ฐฐ์ค‘์ธ ๊ฐ์ฒด์˜ ์ƒํƒœ์ •๋ณด๋ฅผ ๊ฐ€์ง€๊ณ  ์ž์‹ ์ด ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ์ƒํƒœ์ •๋ณด๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๊ฒƒ์€ notify๊ฐ€ ์ด๋ฃจ์–ด์ง„ ๋’ค์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด notify๋Š” CS, CO, ๋˜๋Š” ์ „ํ˜€ ๋‹ค๋ฅธ ์ข…๋ฅ˜์˜ ๊ฐ์ฒด๊ฐ€ ํ˜ธ์ถœ ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

 


ํŒจํ„ด ์‚ฌ์šฉ๋ฒ•

    1. Differentiate between the core (or independent) functionality and the optional (or dependent) functionality.
    2. Model the independent functionality with a "subject" abstraction.
    3. Model the dependent functionality with an "observer" hierarchy.
    4. The Subject is coupled only to the Observer base class.
    5. The client configures the number and type of Observers.
    6. Observers register themselves with the Subject.
    7. The Subject broadcasts events to all registered Observers.
    8. The Subject may "push" information at the Observers, or, the Observers may "pull" the information they need from the Subject.

 


ํŒจํ„ด ์‚ฌ์šฉ์˜ ์žฅ๋‹จ์  ( Consequences ):  


The Observer pattern lets you vary subjects and observers independently. You can reuse subjects without reusing their observers, and vice versa. It lets you add observers without modifying the subject or other observers.

Further benefits and liabilities of the Observer pattern include thefollowing:  


1. Abstract coupling between Subject and Observer. All a subject knows is that it has a list of observers, each conforming to the simple interface of the abstract Observer class.The subject doesn't know the concrete class of any observer. Thus the coupling between subjects and observers is abstract and minimal.

Because Subject and Observer aren't tightly coupled, they can belong to different layers of abstraction in a system. A lower-level subject can communicate and inform a higher-level observer, thereby keeping the system's layering intact. If Subject and Observer are lumped together, then the resulting object must either span two layers (and violate the layering), or it must be forced to live in one layer or the other (which might compromise the layering abstraction).  


2. Support for broadcast communication. Unlike an ordinary request, the notification that a subject sends needn't specify its receiver. The notification is broadcast automatically to all interested objects that subscribed to it. The subject doesn't care how many interested objects exist; its only responsibility is to notify its observers. This gives you the freedom to add and remove observers at any time. It's up to the observer to handle or ignore a notification.  


3. Unexpected updates. Because observers have no knowledge of each other's presence, they can be blind to the ultimate cost of changing the subject. A seemingly innocuous operation on the subject may cause a cascade of updates to observers and their dependent objects. Moreover, dependency criteria that aren't well-defined or maintained usually lead to spurious updates, which can be hard to track down.

This problem is aggravated by the fact that the simple update protocol provides no details on what changed in the subject. Without additional protocol to help observers discover what changed, they maybe forced to work hard to deduce the changes.




๊ด€๋ จ ํŒจํ„ด๋“ค :  

    • Mediator : Byencapsulating complex update semantics, the ChangeManager acts asmediator between subjects and observers.
    • Singleton :The ChangeManager may use the Singleton pattern to make it uniqueand globally accessible.


์ถ”๊ฐ€ ์ •๋ณด :       

    • 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. Command normally specifies a sender-receiver connection with a subclass. Mediator has senders and receivers reference each other indirectly. Observer defines a very decoupled interface that allows for multiple receivers to be configured at run-time.
    • Mediator and Observer are competing patterns. The difference between them is that Observer distributes communication by introducing "observer" and "subject" objects, whereas a Mediator object encapsulates the communication between other objects. We've found it easier to make reusable Observers and Subjects than to make reusable Mediators.
    • On the other hand, Mediator can leverage Observer for dynamically registering colleagues and communicating with them.


 

 


 

์ถœ์ฒ˜ :  http://sourcemaking.com/design_patterns/observer

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


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.

์ด ํŒจํ„ด๋“ค์€ ๊ฐ์ฒด๋“ค ์‚ฌ์ด์˜ ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜์— ๊ด€์‹ฌ์„ ๊ฐ€์ง„๋‹ค.

 

์˜ค๋Š˜ ์‚ดํŽด๋ณผ  Mediator ํŒจํ„ด์€ Behavioral ํŒจํ„ด์— ์†ํ•ฉ๋‹ˆ๋‹ค. 

 

Mediator Pattern Structure

 



์ „ํ˜•์ ์ธ ๊ฐ์ฒด ๊ตฌ์กฐ๋Š” ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค.




  

ํŒจํ„ด์˜ ๋ชฉ์  ( Intent ) :  

Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently.


ํŒจํ„ด์ด ๋‚˜์˜ค๊ฒŒ ๋œ ๋™๊ธฐ ( Motivation ) :

    We want to design reusable components, but dependencies between the potentially reusable pieces demonstrates the "spaghetti code" phenomenon. ๊ฐœ๋ฐœ์ž๋“ค์€ ๋ณดํ†ต ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ปดํฌ๋„ŒํŠธ๋“ค์„ ๋งŒ๋“ค๊ณ  ์‹ถ์–ดํ•˜์ง€๋งŒ ์ž ์žฌ์ ์œผ๋กœ ์žฌ์‚ฌ์šฉ๊ฐ€๋Šฅํ•œ ์ฝ”๋“œ๋“ค์˜ ์˜์กด์„ฑ์ด ์ผ๋ช… "์ŠคํŒŒ๊ฒŒํ‹ฐ ์ฝ”๋“œ"๋ฅผ ๋ฐœ์ƒ์‹œํ‚ค๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ŠคํŒŒ๊ฒŒํ‹ฐ ์ฝ”๋“œ๋ผ๋Š” ๊ฒƒ์€ ๊ฑฐ๋ฏธ์ค„์ฒ˜๋Ÿผ ๋’ค์ฃฝ๋ฐ•์ฃฝ ์˜์กด์„ฑ์ด ์กด์žฌํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

 

 

์œ ๋‹‰์Šค๋‚˜ ๋ฆฌ๋ˆ…์Šค ์‹œ์Šคํ…œ์— ์žˆ๋Š” ์‚ฌ์šฉ์ž ํผ๋ฏธ์…˜ ์‹œ์Šคํ…œ์„ ์˜ˆ๋กœ ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ํ•œ ์‚ฌ์šฉ์ž๋Š” ์—ฌ๋Ÿฌ ๊ทธ๋ฃน์— ์†ํ•ด์žˆ์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ ํ•œ ๊ทธ๋ฃน์€ ์—ฌ๋Ÿฌ ์‚ฌ์šฉ์ž๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์•„๋ž˜ ๊ทธ๋ฆผ ์ฒ˜๋Ÿผ ๋ง์ด์ฃ . 


์œ„ ์‹œ์Šคํ…œ์„ ๊ตฌํ˜„ํ•œ๋‹ค๊ณ  ํ•ด๋ณด์ž๊ตฌ์š”. ๊ทธ๋Ÿผ User ๊ฐ์ฒด๋“ค๊ณผ Group๊ฐ์ฒด๋“ค ์‚ฌ์ด์— ์—ฐ๊ฒฐ๊ณ ๋ฆฌ๊ฐ€ ์žˆ๊ฒ ์ฃ ? ๊ทธ ์—ฐ๊ฒฐ๊ณ ๋ฆฌ ๋•Œ๋ฌธ์— User๊ฐ์ฒด๋‚˜ Group๊ฐ์ฒด๊ฐ€ ๋ณ€๊ฒฝ๋  ๋•Œ ์„œ๋กœ ์˜ํ–ฅ์„ ๋ฏธ์น˜๊ฒŒ ๋ ๊ฒ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ๋‘˜ ์‚ฌ์ด์˜ ๊ด€๊ณ„๋งŒ์„ ์ •์˜ํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ๋”ฐ๋กœ ๋งŒ๋“ค๋ฉด ์–ด๋–จ ๊นŒ์š”? User๊ฐ์ฒด๋‚˜ Group๊ฐ์ฒด๊ฐ€ ๋ณ€๊ฒฝ๋˜์–ด๋„ ์„œ๋กœ์—๊ฒŒ ์˜ํ–ฅ์„ ๋ฏธ์น˜๊ฒŒ ๋  ์ผ์ด ์‚ฌ๋ผ์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ, ์ˆ˜๋งŽ์€ ๊ด€๊ณ„๋“ค์„ ์‰ฝ๊ฒŒ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋  ๋ฟ์•„๋‹ˆ๋ผ ์ˆ˜์ •ํ•˜๋Š” ์ผ๋„ ์‰ฌ์›Œ์งˆ ๊ฒ๋‹ˆ๋‹ค. 

 

์—ฌ๊ธฐ์„œ ๊ด€๊ณ„๋ฅผ ์ •์˜ํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ์ค‘์žฌ์ž ๊ฐ์ฒด๋ผ๊ณ  ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ค‘์žฌ์ž ๊ฐ์ฒด๋Š” ๋‹ค์Œ ์—ญํ• ๋“ค์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. 

  1. encapsulates all interconnections
  2. acts as the hub of communication
  3. is responsible for controlling and coordinating the interactions of its clients
  4. promotes loose coupling by keeping objects from referring to each other explicitly


์œ ์šฉ์„ฑ ( Applicability ) :

 

Use the Mediator pattern when

  • a set of objects communicate in well-defined but complex ways. The resulting inter dependencies are unstructured and difficult to understand.

  • reusing an object is difficult because it refers to and communicates with many other objects.

  • a behavior that's distributed between several classes should be customizable without a lot of subclassing.


๋“ฑ์žฅ ์ธ๋ฌผ ( Participants ) :

  • Mediator
    o
    defines an interface for communicating with Colleague objects.
  • ConcreteMediator
    o
    implements cooperative behavior by coordinating Colleague objects.
    o
    knows and maintains its colleagues.
  • Colleague classes
    o
    each Colleague class knows its Mediator object.
    o
    each colleague communicates with its mediator whenever it would have otherwise communicated with another colleague.


์›๋ฆฌ ( Collaborations ) :  

  • Colleagues send and receive requests from a Mediator object. The mediator implements the cooperative behavior by routing requests between the appropriate colleague(s).


ํŒจํ„ด ์‚ฌ์šฉ๋ฒ•

  1. Identify a collection of interacting objects that would benefit from mutual decoupling.
  2. Encapsulate those interactions in the abstraction of a new class.
  3. Create an instance of that new class and rework all "peer" objects to interact with the Mediator only.
  4. Balance the principle of decoupling with the principle of distributing responsibility evenly.
  5. Be careful not to create a "controller" or "god" object.


ํŒจํ„ด ์‚ฌ์šฉ์˜ ์žฅ๋‹จ์  ( Consequences ): 

The Mediator pattern has the following benefits and drawbacks:

  1. It limits subclassing. A mediator localizes behavior that otherwise would be distributed amongseveral objects. Changing this behavior requires subclassing Mediatoronly; Colleague classes can be reused as is.

  2. It decouples colleagues. A mediator promotes loose coupling between colleagues. You can vary and reuse Colleague and Mediator classes independently.

  3. It simplifies object protocols. A mediator replaces many-to-many interactions with one-to-many interactions between the mediator and its colleagues. One-to-many relationships are easier to understand, maintain, and extend.

  4. It abstracts how objects cooperate. Making mediation an independent concept and encapsulating it in an object lets you focus on how objects interact apart from their individual behavior. That can help clarify how objects interact in a system.

  5. It centralizes control. The Mediator pattern trades complexity of interaction for complexity in the mediator. Because a mediator encapsulates protocols, it can become more complex than any individual colleague. This can make the mediator itself a monolith that's hard to maintain.

๊ด€๋ จ ํŒจํ„ด๋“ค :  

 

Facade differsfrom Mediator in that it abstracts a subsystem of objects to providea more convenient interface. Its protocol is uni-directional; thatis, Facade objects make requests of the subsystem classes but notvice versa. In contrast, Mediator enables cooperative behavior that colleague objects don't or can't provide, and the protocol is multi-directional.

Colleagues can communicate with the mediator using the Observer pattern.


์ถ”๊ฐ€ ์ •๋ณด :      

  • 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. Command normally specifies a sender-receiver connection with a subclass. Mediator has senders and receivers reference each other indirectly. Observer defines a very decoupled interface that allows for multiple receivers to be configured at run-time.
  • Mediator and Observer are competing patterns. The difference between them is that Observer distributes communication by introducing "observer" and "subject" objects, whereas a Mediator object encapsulates the communication between other objects. We've found it easier to make reusable Observers and Subjects than to make reusable Mediators.
  • On the other hand, Mediator can leverage Observer for dynamically registering colleagues and communicating with them.
  • Mediator is similar to Facade in that it abstracts functionality of existing classes. Mediator abstracts/centralizes arbitrary communication between colleague objects, it routinely "adds value", and it is known/referenced by the colleague objects (i.e. it defines a multidirectional protocol). In contrast, Facade defines a simpler interface to a subsystem, it doesn't add new functionality, and it is not known by the subsystem classes (i.e. it defines a unidirectional protocol where it makes requests of the subsystem classes but not vice versa).

 

์ถœ์ฒ˜ :  http://sourcemaking.com/design_patterns/mediator

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

 


๋””์ž์ธ ํŒจํ„ด์— ๋Œ€ํ•ด์„œ ํ•œ๋ฒˆ ํ›‘์–ด๋ณด๊ธด ํ–ˆ์—ˆ๋Š”๋ฐ ๋‹ค์‹œํ•œ๋ฒˆ ๋ณต์Šตํ•˜๋Š” ์ฐจ์›์—์„œ ํ•˜๋‚˜ํ•˜๋‚˜ ์ •๋ฆฌํ•˜๋Š” ์‹œ๊ฐ„์„ ๊ฐ–๊ณ  ์‹ถ์—ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์˜ค๋Š˜์€ ๊ทธ ์ฒซ์งธ ๋‚ .

 

์˜ค ๋Š˜ ํ•จ๊ป˜ ๋ณผ ๋””์ž์ธํŒจํ„ด์€ Iterator ํŒจํ„ด์ด๋‹ค. ๋‚ด์šฉ์˜ ๋Œ€๋ถ€๋ถ„์€ GoF์˜ ๋””์ž์ธํŒจํ„ด ์ฑ…์—์„œ ๋ฐœ์ทŒ๋ฅผ ํ•˜๊ฒŒ๋  ๊ฒƒ์ž„์„ ๋ฐํžŒ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์˜๋ฌธ์„ ํ•œ๊ธ€๋กœ ๋ฒˆ์—ญ์„ ํ•˜๊ฒŒ ๋ ํ…๋ฐ ์ „๋ฌธ๋ฒˆ์—ญ๊ฐ€๊ฐ€ ์•„๋‹ˆ๋ฏ€๋กœ ํ•œ๊ธ€ ๋ฒˆ์—ญ๋ณธ์ด ์ดํ•ด๊ฐ€ ์•ˆ๊ฐ„๋‹ค๊ณ  ๋Š๋ผ๋ฉด ์˜๋ฌธ ์›๋ณธ์„ ์ฝ์–ด๋ณด์‹œ๊ธธ ๊ถŒ์œ ํ•œ๋‹ค.

 

๊ทธ๋Ÿผ ์‹œ์ž‘ํ•ด ๋ณผ๊นŒ?

 

์šฐ์„  GoF์˜ ๋””์ž์ธ ํŒจํ„ด์€ ์•„๋ž˜์™€ ๊ฐ™์ด ํฌ๊ฒŒ 3๊ฐ€์ง€ ์ข…๋ฅ˜๋กœ ๋ถ„๋ฅ˜๋œ๋‹ค.

 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.

์ด ํŒจํ„ด๋“ค์€ ๊ฐ์ฒด๋“ค ์‚ฌ์ด์˜ ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜์— ๊ด€์‹ฌ์„ ๊ฐ€์ง„๋‹ค.

 

์ด์ œ ์‚ดํŽด๋ณผ Iterator ํŒจํ„ด์€ Behavioral ํŒจํ„ด์— ์†ํ•œ๋‹ค. 

Iterator๋Š” ์ž๋ฐ”์˜ Iterator์™€ ๊ฐ™์€ ๊ฒƒ์„ ๋งํ•œ๋‹ค. ์‚ฌ์ „์  ์˜๋ฏธ๋กœ "๋ฐ˜๋ณต์ž"๋ผ๊ณ  ๋ถˆ๋ฆฌ๋Š” iterator๋Š” ์ž๋ฐ”์˜ ๊ฒฝ์šฐ collection๊ฐ์ฒด์—์„œ ์‚ฌ์šฉ์ด ๋œ๋‹ค. ์˜ค๋ผํด์—์„œ ์ œ๊ณตํ•˜๋Š” Iterator์— ๋Œ€ํ•œ ์ •๋ณด๋Š” ์ด๊ณณ์—์„œ ํ™•์ธํ•˜๋ฉด๋œ๋‹ค. ์ด์ฒ˜๋Ÿผ ์•ž์œผ๋กœ ์‚ดํŽด๋ณผ ๋ชจ๋“  ํŒจํ„ด๋“ค์€ ๊ทธ ์ด๋ฆ„์—์„œ ์ด ํŒจํ„ด์ด ์–ด๋–ค ํŒจํ„ด์ธ์ง€ ํŒŒ์•…ํ•  ์ˆ˜๊ฐ€ ์žˆ๋‹ค.

 

Iterator Pattern Structure

 

 


ํŒจํ„ด์˜ ๋ชฉ์  :
Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.

 

Iterator ํŒจํ„ด์˜ ๋ชฉ์ ์€ aggregate object ( ex. List )๋ฅผ ์ˆœ์ฐจ์ ์œผ๋กœ ์•ก์„ธ์Šค ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ๋ฌผ๋ก  ์ด ๊ณผ์ •์—์„œ ๊ฐœ๋ฐœ์ž๋Š” object๊ฐ€ ์–ด๋–ค์‹์œผ๋กœ ๊ตฌํ˜„์ด ๋˜์–ด์žˆ๋Š”์ง€๋Š” ์•Œ ํ•„์š”๊ฐ€ ์—†์œผ๋ฏ€๋กœ object์˜ ๊ตฌํ˜„๋ถ€๋ฅผ ๋…ธ์ถœ์‹œํ‚ค์ง€ ์•Š๋Š”๋‹ค.

 

์œ ์šฉ์„ฑ ( Applicability ) :

ยท to access an aggregate object's contents without exposing its internal representation.

๋‚ด๋ถ€ ๊ตฌํ˜„์„ ๋…ธ์ถœ์‹œํ‚ค์ง€ ์•Š์œผ๋ฉด์„œ ์ง‘์•ฝ ๊ฐ์ฒด์˜ ๋‚ด์šฉ๋ฌผ์— ์ ‘๊ทผํ•˜๊ณ ์ž ํ•  ๋•Œ
ยท to support multiple traversals of aggregate objects.

์ง‘์•ฝ(์ง‘ํ•ฉ) ๊ฐ์ฒด๋“ค์— ๋Œ€ํ•ด ๋‹ค์–‘ํ•œ ํƒ์ƒ‰๊ฒฝ๋กœ(?)๋ฅผ ์ง€์›ํ•˜๊ณ ์ž ํ•  ๋•Œ
ยท to provide a uniform interface for traversing different aggregate structures (that is, to support polymorphic iteration).

๋‹ค๋ฅธ ์ง‘์•ฝ(์ง‘ํ•ฉ)๊ตฌ์กฐ๋“ค์„ ํƒ์ƒ‰ํ•˜๊ธฐ์œ„ํ•œ ํ†ต์ผ๋œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•˜๊ณ ์ž ํ•  ๋•Œ (์ฆ‰, ๋‹คํ˜•์  iteration์„ ์ง€์›ํ•˜๊ณ ์ž ํ•  ๋•Œ )

 

๋“ฑ์žฅ ์ธ๋ฌผ :
ยท Iterator
o defines an interface for accessing and traversing elements.
ยท ConcreteIterator
o implements the Iterator interface.
o keeps track of the current position in the traversal of the aggregate.
ยท Aggregate
o defines an interface for creating an Iterator object.
ยท ConcreteAggregate
o implements the Iterator creation interface to return an instance of the proper ConcreteIterator.

 

์žฅ๋‹จ์  :
1. It supports variations in the traversal of an aggregate.Complex aggregates
may be traversed in many ways. For example, code generation and semantic checking involve traversing parse trees. Code generation may traverse the parse tree inorder or preorder.Iterators make it easy to change the traversal algorithm: Just replace the iterator instance with a different
one. You can also define Iterator subclasses to support new traversals.
2. Iterators simplify the Aggregate interface.Iterator's traversal interface obviates the need for a similar interface in Aggregate, thereby simplifying the aggregate's interface.
3. More than one traversal can be pending on an aggregate.An iterator keeps track of its own traversal state. Therefore you can have more than one traversal in progress at once.


๊ด€๋ จ ํŒจํ„ด๋“ค : 

Composite : Iterators are often applied to recursive structures such as Composites.
Factory Method : Polymorphic iterators rely on factory methods to instantiate theappropriate Iterator subclass.
Memento is often used in conjunction with the Iterator pattern. An iterator can use a memento to capture the state of an iteration. The iterator stores the memento internally. 

 

 

 


์ถœ์ฒ˜ : Design Patterns : Element of Reusable Object Oriented Software ( by GoF, 1994 )

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.

์ด ํŒจํ„ด๋“ค์€ ๊ฐ์ฒด๋“ค ์‚ฌ์ด์˜ ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜์— ๊ด€์‹ฌ์„ ๊ฐ€์ง„๋‹ค.

 

์˜ค๋Š˜ ์‚ดํŽด๋ณผ  Command ( ๋ช…๋ น, ์ปค๋งจ๋“œ )ํŒจํ„ด์€ Behavioral ํŒจํ„ด์— ์†ํ•œ๋‹ค.   

๋ช…๋ น ํŒจํ„ด์ด๋ผ~ ๋ช…๋ น์„ ๋‚ด๋ฆฌ๋Š” ํŒจํ„ด์ด๋ผ๋Š” ๊ฑฐ๊ฒ ์ฃ ??

์ž์„ธํžˆ ์•Œ์•„๋ด…์‹œ๋‹ค.

 

Command Pattern Structure

 


 


  

ํŒจํ„ด์˜ ๋ชฉ์  ( Intent ) :  

Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.  

๋ช…๋ น ํŒจํ„ด, ์ปค๋งจ๋“œ ํŒจํ„ด์€ ํ•˜๋‚˜์˜ ์š”์ฒญ์„ ํ•˜๋‚˜์˜ ๊ฐ์ฒด๋กœ ์บก์Šํ™”ํ•˜์—ฌ ์š”์ฒญ์„ ํŒŒ๋ผ๋ฏธํ„ฐ์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ๋” ํ•ด์ฃผ๋ฉฐ ๋˜๋Œ๋ฆฌ๊ธฐ ๊ธฐ๋Šฅ์„ ์ง€์›ํ•œ๋‹ค. 


ํŒจํ„ด์ด ๋‚˜์˜ค๊ฒŒ ๋œ ๋™๊ธฐ ( Motivation ) :

   Need to issue requests to objects without knowing anything about the operation being requested or the receiver of the request.

์ด ํŒจํ„ด์ด ๋‚˜์˜ค๊ฒŒ ๋œ ๋™๊ธฐ๋ผ ํ•˜๋ฉด ๊ฐ„๋‹จํžˆ ๋งํ•ด์„œ ์š”์ฒญ์„ ๋‚ ๋ฆด ๋•Œ ์–ด๋–ค ์š”์ฒญ์ด ๋‚ ์•„๊ฐ€๋Š”์ง€ ๋ฆฌ์‹œ๋ฒ„๊ฐ€ ๋ˆ„๊ตฌ์ธ์ง€์— ๋Œ€ํ•ด์„œ ๋ชฐ๋ผ๋„ ๋˜๊ฒŒ๋” ํ•˜๊ธฐ ์œ„ํ•ด์„œ ์ž…๋‹ˆ๋‹ค.  

 

GoF์˜ ๋””์ž์ธ ํŒจํ„ด์—์„œ๋Š” ์‘์šฉํ”„๋กœ๊ทธ๋žจ์˜ ๋ฉ”๋‰ด๋ฅผ ํด๋ฆญํ–ˆ์„ ๋•Œ ์–ด๋–ค ๋ช…๋ น์„ ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์„ ์˜ˆ๋กœ ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.


 ์œ„ ํด๋ž˜์Šค ๋‹ค์ด์–ด๊ทธ๋žจ์€ ์‘์šฉํ”„๋žจ์—์„œ ๋ฉ”๋‰ด๋ฅผ ์„ ํƒํ•ด์„œ ๋“ค์–ด๊ฐ€๊ณ  ํ•˜์œ„๋ฉ”๋‰ด๋ฅผ ํด๋ฆญํ–ˆ์„ ๋•Œ ํŠน์ • ๋ช…๋ น์ด ์‹คํ–‰๋˜๋Š” ๊ฒƒ์„ ๋‚˜ํƒ€๋‚ด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.๋ฉ”๋‰ด์•„์ดํ…œ์€ ์ปค๋งจ๋“œ ๊ฐ์ฒด๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๊ณ  ์ด ์ปค๋งจ๋“œ ๊ฐ์ฒด๋Š” ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์ด ๊ตฌํ˜„๋˜์–ด ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ฉ”๋‰ด์•„์ดํ…œ๊ฐ์ฒด๋Š” ์ด ์ปค๋งจ๋“œ๊ฐ์ฒด๊ฐ€ ๋ฌด์Šจ ๋ช…๋ น์„ ์‹คํ–‰ํ•˜๋Š” ์ง€๋Š” ๋ชจ๋ฅด๊ณ  ๊ทธ๋ƒฅ ์‹คํ–‰๋งŒ ์‹œํ‚ค๋Š” ๊ฒ๋‹ˆ๋‹ค. 

 

์œ ์šฉ์„ฑ ( Applicability ) :

Use the Command pattern when you want to

๋ช…๋ น ํŒจํ„ด์€ ์ด๋Ÿด ๋•Œ ์“ฐ์„ธ์š”. 

โ€ข parameterize objects by an action to perform, as MenuItem objects did above. You can express such parameterization in a procedural language with a callback function, that is, a function that's registered somewhere to be called at a later point. Commands are an object-oriented replacement for callbacks.  

 

โ€ข specify, queue, and execute requests at different times. A Command object can have a lifetime independent of the original request. If the receiver of a request can be represented in an address space-independent way, then you can transfer a command object for the request to a different process and fulfill the request there.

 

โ€ข support undo. The Command's Execute operation can store state for reversing its effects in the command itself. The Command interface must have an added Unexecute operation that reverses the effects of a previous call to Execute. Executed commands are stored in a history list. Unlimited-level undo and redo is achieved by traversing this list backwards and forwards calling Unexecute and Execute, respectively.

 

โ€ข support logging changes so that they can be reapplied in case of a system crash. By augmenting the Command interface with load and store operations, you can keep a persistent log of changes. Recovering from a crash involves reloading logged commands from disk and reexecuting them with the Execute operation.

 

โ€ข structure a system around high-level operations built on primitives operations. Such a structure is common in information systems that support transactions. A transaction encapsulates a set of changes to data. The Command pattern offers a way to model transactions. Commands have a common interface, letting you invoke all transactions the same way. The pattern also makes it easy to extend the system with new transactions.



๋“ฑ์žฅ ์ธ๋ฌผ ( Participants ) :


โ€ข Command

o declares an interface for executing an operation.  

โ€ข ConcreteCommand

o defines a binding between a Receiver object and an action.

o implements Execute by invoking the corresponding operation(s) on Receiver.

โ€ข Client 

           o creates a ConcreteCommand object and sets its receiver.
โ€ข Invoker

           o asks the command to carry out the request.
โ€ข Receiver

           o
knows how to perform the operations associated with carrying out a request. Any class may serve as a Receiver.


์›๋ฆฌ ( Collaborations ) :

  • The client creates a ConcreteCommand object and specifies its receiver.
  • An Invoker object stores the ConcreteCommand object.
  • The invoker issues a request by calling Execute on the command. When commands are undoable, ConcreteCommand stores state for undoing thecommand prior to invoking Execute.

  • The ConcreteCommand object invokes operations on its receiver to carryout the request.

 

The following diagram shows the interactions between these objects.It illustrates how Command decouples the invoker from the receiver(and the request it carries out).

 

 


ํŒจํ„ด ์‚ฌ์šฉ๋ฒ•

  1. Define a Command interface with a method signature like execute().
  2. Create one or more derived classes that encapsulate some subset of the following: a "receiver" object, the method to invoke, the arguments to pass.
  3. Instantiate a Command object for each deferred execution request.
  4. Pass the Command object from the creator (aka sender) to the invoker (aka receiver).
  5. The invoker decides when to execute().

ํŒจํ„ด ์‚ฌ์šฉ์˜ ์žฅ๋‹จ์  ( Consequences ): 

The Command pattern has the following consequences:  

  1. Command decouples the object that invokes the operation from the one that knows how to perform it.
  2. Commands are first-class objects.They can be manipulated and extended like any other object.
  3. You can assemble commands into a composite command. In general, composite commands are an instance of the Composite pattern.
  4. It's easy to add new Commands, because you don't have to change existing classes.

๊ด€๋ จ ํŒจํ„ด๋“ค :  

A Composite can be used to implement MacroCommands.
A Memento can keep state the command requires to undo its effect.

A command that must be copied before being placed on the historylist acts as a Prototype.


์ถ”๊ฐ€ ์ •๋ณด :     

  • Chain of Responsibility, Command, Mediator, and Observer, address how you can decouple senders and receivers, but with different trade-offs. Command normally specifies a sender-receiver connection with a subclass.
  • Chain of Responsibility can use Command to represent requests as objects.
  • Command and Memento act as magic tokens to be passed around and invoked at a later time. In Command, the token represents a request; in Memento, it represents the internal state of an object at a particular time. Polymorphism is important to Command, but not to Memento because its interface is so narrow that a memento can only be passed as a value.
  • Command can use Memento to maintain the state required for an undo operation.
  • MacroCommands can be implemented with Composite.
  • A Command that must be copied before being placed on a history list acts as a Prototype.
  • Two important aspects of the Command pattern: interface separation (the invoker is isolated from the receiver), time separation (stores a ready-to-go processing request that's to be stated later).

 

์ถœ์ฒ˜ :  http://sourcemaking.com/design_patterns/command

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

 


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.

์ด ํŒจํ„ด๋“ค์€ ๊ฐ์ฒด๋“ค ์‚ฌ์ด์˜ ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜์— ๊ด€์‹ฌ์„ ๊ฐ€์ง„๋‹ค.

 

์˜ค๋Š˜ ์‚ดํŽด๋ณผ  Composite ํŒจํ„ด์€ Structural ํŒจํ„ด์— ์†ํ•œ๋‹ค.  

 

Composite Pattern Structure

 

A typical Composite object structure might look like this:



ํŒจํ„ด์˜ ๋ชฉ์  ( Intent ) : 

 

Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.

์ปด ํฌ์ง€ํŠธ ํŒจํ„ด์€ ๊ฐ์ฒด๋“ค์˜ ๊ด€๊ณ„๋ฅผ ํŠธ๋ฆฌ ๊ตฌ์กฐ๋กœ ๊ตฌ์„ฑํ•˜์—ฌ ๋ถ€๋ถ„-์ „์ฒด ๊ณ„์ธต์„ ํ‘œํ˜„ํ•˜๋Š” ํŒจํ„ด์œผ๋กœ, ์‚ฌ์šฉ์ž๊ฐ€ ๋‹จ์ผ ๊ฐ์ฒด์™€ ๋ณตํ•ฉ ๊ฐ์ฒด ๋ชจ๋‘ ๋™์ผํ•˜๊ฒŒ ๋‹ค๋ฃจ๋„๋ก ํ•˜๋Š” ํŒจํ„ด์ด๋‹ค. ๋”ฐ๋ผ์„œ, {๊ฐ์ฒด์˜ ๊ทธ๋ฃน}๊ณผ {ํ•˜๋‚˜์˜ ๊ฐ์ฒด}๊ฐ€ ๋™์ผํ•œ ํ–‰์œ„๋ฅผ ํ•  ๋•Œ ์ ์šฉ๋˜์•ผ ํ•˜๋ฉฐ, ๋˜ํ•œ ํŠธ๋ฆฌ๊ตฌ์กฐ๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ๋‹ค. 

 

ํŒจํ„ด์ด ๋‚˜์˜ค๊ฒŒ ๋œ ๋™๊ธฐ ( Motivation ) :


๊ทธ ๋ž˜ํ”ฝ ํˆด์€ ์‚ฌ์šฉ์ž๋“ค๋กœ ํ•˜์—ฌ๊ธˆ ๊ฐ„๋‹จํ•œ ์ปดํฌ๋„ŒํŠธ ( ex. ์„ , ์‚ฌ๊ฐํ˜•, ๋ฌธ์ž, ๊ทธ๋ฆผ ๋“ฑ๋“ฑ )๋ถ€ํ„ฐ ๋ณต์žกํ•œ ์ปดํฌ๋„ŒํŠธ ( ex. ๊ธ€์”จ๊ฐ€ ๋“ค์–ด๊ฐ„ ์‚ฌ๊ฐํ˜• )์— ์ด๋ฅด๊ธฐ๊นŒ์ง€ ๊ฐ„๋‹จํ•˜๊ฒŒ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ค€๋‹ค. ์ด๋ฅผ ๊ฐ„๋‹จํžˆ ๊ตฌํ˜„ํ•˜์ž๋ฉด ๊ฐ๊ฐ์˜ ํด๋ž˜์Šค๋ฅผ ์ •์˜ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. Lineํด๋ž˜์Šค, Rectangle ํด๋ž˜์Šค๋ฅผ ๊ฐ๊ฐ ์ •์˜ํ•ด์„œ ๊ฐ€์ ธ๋‹ค๊ฐ€ ์“ฐ๋ฉด ๋˜๋Š”๋ฐ ๋‹จ์ˆœํžˆ ์ด๋ ‡๊ฒŒ ๊ตฌํ˜„์„ ํ•˜๋ฉด ๋‚˜์ค‘์— ํฐ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒ ํ•  ์ˆ˜ ์žˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ํ”„๋ฆฌ๋ฏธํ‹ฐ๋ธŒ ๊ฐ์ฒด์™€ ์ปจํ…Œ์ด๋„ˆ ๊ฐ์ฒด๋ฅผ ๋‹ค๋ฅด๊ฒŒ ๋‹ค๋ฃจ์–ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์ด๊ฒŒ ๋ฌด์Šจ ์†Œ๋ฆฌ๋ƒ ํ•˜๋ฉด, ๊ทธ๋ฆผํŒ์—์„œ ํ•˜๋‚˜์˜ ์ง์„ ์„ ๊ทธ์—ˆ๋‹ค๊ณ  ํ•˜์ž. ์ด ์ง์„ ์€ ์‹œ์ž‘์ ๊ณผ ๋์  ์ขŒํ‘œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ํ•˜๋‚˜์˜ ๊ฐ์ฒด๊ฒ ์ง€? ๊ทธ๋Ÿฐ๋ฐ ๋˜๋‹ค๋ฅธ ์ง์„ ์„ ๊ทธ์—ˆ๋‹ค. ๋‘๋ฒˆ์งธ ์ง์„  ์—ญ์‹œ ์‹œ์ž‘์ ๊ณผ ๋์  ์ขŒํ‘œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๊ฒ ์ง€. ๊ทธ๋Ÿฐ๋ฐ ์ด ๋‘๊ฐœ๋ฅผ ํ•œ๊บผ๋ฒˆ์— ์ €์žฅํ•˜๋ ค๋ฉด ๋‘๊ฐœ์˜ ์ง์„  ๊ฐ์ฒด๋ฅผ ๊ฐ€์ง€๊ณ ์žˆ๋Š” ๋˜๋‹ค๋ฅธ wrapper ํด๋ž˜์Šค๊ฐ€ ์žˆ์–ด์•ผ ํ•  ๊ฒƒ์ด๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์ง์„ ์ด ๋ช‡๊ฐœ๊ฐ€ ๋ ์ง€ ๋ˆ„๊ฐ€ ์•„๋ƒ? ๊ทธ๋ฆฌ๋Š” ์‚ฌ๋žŒ์ด ๋ช‡๊ฐœ๋ฅผ ๊ทธ๋ฆด์ง€๋Š” ์•„๋ฌด๋„ ๋ชจ๋ฅด์ž–์•„? ๊ทธ๋ž˜์„œ ์ด๋Ÿฐ ์‹์œผ๋กœ ์ ‘๊ทผํ•˜๋‹ค๊ฐ€๋Š” ํ‰์ƒํ•ด๋„ ์ œ๋Œ€๋กœ๋œ ๊ทธ๋ž˜ํ”ฝ ํˆด์„ ๋ชป ๋งŒ๋“ค ๊ฒƒ์ด๋‹ค. ๊ทธ๋ž˜์„œ ๋‚˜์˜จ ๊ฒƒ์ด ๋ฐ”๋กœ ์ด ์ปดํฌ์ง€ํŠธ ํŒจํ„ด์ธ ๊ฒƒ์ด๋‹ค. ์•„๋ž˜ ๋‹ค์ด์–ด๊ทธ๋žจ์„ ๋ณด์ž.


 

์œ„ ๋‹ค์ด์–ด๊ทธ๋žจ์€ ์ง์„ , ์‚ฌ๊ฐํ˜•, ๋ฌธ์ž, ๊ทธ๋ฆผ์„ ๋ชจ๋‘ ๊ทธ๋ž˜ํ”ฝ ๊ฐ์ฒด๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ํด๋ž˜์Šค๋กœ ๋งŒ๋“ค์–ด ๋ฒ„๋ฆฌ๊ณ  ๊ฐ ๊ทธ๋ž˜ํ”ฝ ํด๋ž˜์Šค๋Š” ์ž์‹์œผ๋กœ ๊ทธ๋ž˜ํ”ฝ ํด๋ž˜์Šค๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋„๋ก ํ–ˆ๋‹ค. ๊ทธ๋ž˜ํ”ฝ ํด๋ž˜์Šค๊ฐ€ ๊ทธ๋ž˜ํ”ฝ ํด๋ž˜์Šค๋ฅผ ์ž์‹์œผ๋กœ ๊ฐ–๋Š”๋‹ค? ์ดํ•ด๊ฐ€ ๋˜๋Š”๊ฐ€? ์˜ˆ๋ฅผ ๋“ค์–ด๋ณด์ž.

๋‚ด ๊ฐ€ ์–ด์ œ ํ•˜๋‚˜์˜ ๊ทธ๋ฆผ์„ ๊ทธ๋ ธ๋‹ค. ์ด ๊ทธ๋ฆผ์€ ์‚ฌ๊ฐํ˜•๊ณผ ์ง์„  ๊ทธ๋ฆฌ๊ณ  ๋ฌธ์ž๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์˜ค๋Š˜ ๋‚˜๋Š” ๋‘๋ฒˆ์งธ ๊ทธ๋ฆผ์„ ๊ทธ๋ฆฌ๋ฉด์„œ ์–ด์ œ ๊ทธ๋ฆฐ ๊ทธ๋ฆผ๊ณผ ๋˜ ๋‹ค๋ฅธ ์„ , ์‚ฌ๊ฐํ˜•์„ ๊ทธ๋ ค๋„ฃ์—ˆ๋‹ค. ์ด๊ฒƒ์„ ๋‹ค์ด์–ด๊ทธ๋žจ์œผ๋กœ ํ‘œํ˜„ํ•œ ๊ฒƒ์ด ์•„๋ž˜ ๊ทธ๋ฆผ์ด๋‹ค.

aPicture, aTest, aLine, aRectangle์€ ๋ชจ๋‘ ๊ทธ๋ž˜ํ”ฝ ๊ฐ์ฒด์ด๋‹ค. ์ด ๊ทธ๋ž˜ํ”ฝ ๊ฐ์ฒด๋“ค์€ ๋˜ ๋‹ค๋ฅธ ๊ทธ๋ž˜ํ”ฝ ๊ฐ์ฒด๋“ค์„ ์ž์‹์œผ๋กœ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. ์ด์ œ ์ดํ•ด๊ฐ€ ๋˜๋Š”๊ฐ€?


์œ ์šฉ์„ฑ ( Applicability ) :

 Use the Composite pattern when
ยท you want to represent part-whole hierarchies of objects.
ยท you want clients to be able to ignore the difference between compositions of objects and individual objects. Clients will treat all objects in the composite structure uniformly.



๋“ฑ์žฅ ์ธ๋ฌผ ( Participants ) :

ยท Component (Graphic)
o declares the interface for objects in the composition.
o implements default behavior for the interface common to all classes, as appropriate.
o declares an interface for accessing and managing its child components.
o (optional) defines an interface for accessing a component's parent in the recursive structure, and implements it if that's appropriate.
ยท Leaf (Rectangle, Line, Text, etc.)
o represents leaf objects in the composition. A leaf has no children.
o defines behavior for primitive objects in the composition.
ยท Composite (Picture) 

o defines behavior for components having children.
o stores child components.
o implements child-related operations in the Component interface.
ยท Client
o manipulates objects in the composition through the Component interface.

 


์›๋ฆฌ ( Collaborations ) :

ยท Clients use the Component class interface to interact with objects in the composite structure. If the recipient is a Leaf, then the request is handled directly. If the recipient is a Composite, then it usually forwards requests to its child components, possibly performing additional operations before and/or after forwarding.


ํŒจํ„ด ์‚ฌ์šฉ์˜ ์žฅ๋‹จ์  ( Consequences ): 

The Composite pattern


ยท defines class hierarchies consisting of primitive objects and composite objects. Primitive objects can be composed into more complex objects, which in turn can be composed, and so on recursively. Wherever client code expects a primitive object, it can also take a composite object.  

ยท makes the client simple. Clients can treat composite structures and individual objects uniformly. Clients normally don't know (and shouldn't care) whether they're dealing with a leaf or a composite component. This simplifies client code, because it avoids having to write tag-and-case-statement-style functions over the classes that define the composition.
ยท makes it easier to add new kinds of components. Newly defined Composite or Leaf subclasses work automatically with existing structures and client code. Clients don't have to be changed for new Component classes.
ยท can make your design overly general. The disadvantage of making it easy to add new components is that it makes it harder to restrict the components of a composite. Sometimes you want a composite to have only certain components. With Composite, you can't rely on the type system to enforce those constraints for you. You'll have to use run-time checks instead.

 

๊ด€๋ จ ํŒจํ„ด๋“ค : 

 Often the component-parent link is used for a Chain of Responsibility.
Decorator is often used with Composite. When decorators and composites are used together, they will usually have a common parent class. So decorators will have to support the Component interface with operations like Add, Remove, and GetChild.
Flyweight lets you share components, but they can no longer refer to their parents.
Iterator can be used to traverse composites.
Visitor localizes operations and behavior that would otherwise be distributed across Composite and Leaf classes.

 

์ถ”๊ฐ€ ์ •๋ณด :

  • Composite and Decorator have similar structure diagrams, reflecting the fact that both rely on recursive composition to organize an open-ended number of objects.
  • Composite can be traversed with Iterator. Visitor can apply an operation over a Composite. Composite could use Chain of Responsibility to let components access global properties through their parent. It could also use Decorator to override these properties on parts of the composition. It could use Observer to tie one object structure to another and State to let a component change its behavior as its state changes.
  • Composite can let you compose a Mediator out of smaller pieces through recursive composition.
  • Decorator is designed to let you add responsibilities to objects without subclassing. Composite's focus is not on embellishment but on representation. These intents are distinct but complementary. Consequently, Composite and Decorator are often used in concert.
  • Flyweight is often combined with Composite to implement shared leaf nodes.

 

์ถœ์ฒ˜ :  http://sourcemaking.com/design_patterns/composite

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

http://www.journaldev.com/1535/composite-design-pattern-in-java-example-tutorial 


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.

์ด ํŒจํ„ด๋“ค์€ ๊ฐ์ฒด๋“ค ์‚ฌ์ด์˜ ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜์— ๊ด€์‹ฌ์„ ๊ฐ€์ง„๋‹ค.

 

์˜ค๋Š˜ ์‚ดํŽด๋ณผ  Facade ํŒจํ„ด์€ Structural ํŒจํ„ด์— ์†ํ•œ๋‹ค.  ์ด ํŒจํ„ด์€ ์ปดํฌ์ง€ํŠธ ํŒจํ„ด๊ณผ ๋น„์Šทํ•œ ๋‹ค์ด์–ด๊ทธ๋žจ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. 

Facade๋Š” ํผ์‚ฌ๋“œ๋ผ๊ณ  ์ฝ๋Š”๋‹ค. ํผ์ผ€์ด๋“œ, ํŒจ์ผ€์ด๋“œ ์ด๋”ด์‹์œผ๋กœ ์ฝ๋Š”๊ฒŒ ์•„๋‹ˆ๋‹ค.

 

Facade Pattern Structure


ํŒจํ„ด์˜ ๋ชฉ์  ( Intent ) : 

 Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.  

ํผ์‚ฌ๋“œ ํŒจํ„ด์€ ์„œ๋ธŒ์‹œ์Šคํ…œ ๋‚ด๋ถ€์— ์žˆ๋Š” ํด๋ž˜์Šค์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ํ•˜๋‚˜์˜ ํ†ตํ•ฉ๋œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•˜๋Š” ํŒจํ„ด์ด๋‹ค. 


ํŒจํ„ด์ด ๋‚˜์˜ค๊ฒŒ ๋œ ๋™๊ธฐ ( Motivation ) :

 

ํฐ ์‹œ์Šคํ…œ์„ ์ž‘์€ ์‹œ์Šคํ…œ์œผ๋กœ ๋‚˜๋ˆ„๋Š” ๊ฒƒ์€ ์‹œ์Šคํ…œ์˜ ๋ณต์žก๋„๋ฅผ ๋‚ฎ์ถฐ์ค€๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋””์ž์ธ์˜ ๊ณตํ†ต ๋ชฉํ‘œ๋Š” ์„œ๋ธŒ์‹œ์Šคํ…œ๋“ค ์‚ฌ์ด์˜ ์˜์กด์„ฑ์„ ์ค„์ด๊ณ  ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜ ํšŸ์ˆ˜๋ฅผ ์ค„์ด๋Š” ๊ฒƒ์ธ๋ฐ ํผ์‚ฌ๋“œ ํŒจํ„ด์ด ์ด๋ฅผ ์œ„ํ•œ ๋ฐฉ๋ฒ•์ค‘ ํ•˜๋‚˜์ด๋‹ค. ์•„๋ž˜ ๊ทธ๋ฆผ์—์„œ ์ปค๋‹ค๋ž€ ์‚ฌ๊ฐํ˜•์ด ์„œ๋ธŒ์‹œ์Šคํ…œ์ด๊ณ  ๊ทธ ์•ˆ์— ์ž‘์€ ์‚ฌ๊ฐํ˜•๋“ค์€ ์„œ๋ธŒ์‹œ์Šคํ…œ์˜ ํด๋ž˜์Šค๋“ค์„ ์˜๋ฏธํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์„œ๋ธŒ์‹œ์Šคํ…œ ๋ฐ–์—๋Š” ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์„œ๋ธŒ์‹œ์Šคํ…œ์— ์ ‘๊ทผํ•  ๋•Œ ์‚ฌ์šฉ๋˜๋Š” ํด๋ž˜์Šค๋“ค์ด ์žˆ๋‹ค. 


๊ทธ๋Ÿฐ๋ฐ ์™ผ์ชฝ ๊ทธ๋ฆผ์„ ๋ณด๋ฉด ์„œ๋ธŒ์‹œ์Šคํ…œ์— ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•ด์„œ ํด๋ผ์ด์–ธํŠธ ํด๋ž˜์Šค๊ฐ€ ์ง์ ‘์ ์œผ๋กœ ์„œ๋ธŒ์‹œ์Šคํ…œ ๋‚ด๋ถ€์˜ ํด๋ž˜์Šค๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋ฐฉ์‹์ด๋‹ค. ๊ทธ๋ฆผ์œผ๋กœ๋ด๋„ ๋ญ”๊ฐ€ ๋ณต์žกํ•ด ๋ณด์ธ๋‹ค. ์„œ๋ธŒ์‹œ์Šคํ…œ์ด ๋ณ€๊ฒฝ๋˜๋ฉด?? ํด๋ผ์ด์–ธํŠธ ์ชฝ์—์„œ๋„ ์ˆ˜์ •ํ•ด์•ผํ•˜๋Š” ๋ถ€๋ถ„์ด ์ƒ๊ธธ ๊ฒƒ์ด๊ณ  ํฐ ํ”„๋กœ์ ํŠธ์˜€๋‹ค๋ฉด ์–ด๋””๋ฅผ ์ˆ˜์ •ํ•ด์•ผ ํ• ์ง€ ์ฐพ์•„๋‚ด๊ธฐ๋„ ํž˜๋“ค๊ฒƒ์ด๋‹ค. ๊ทธ๋ž˜์„œ ์ด๋ฅผ ํผ์‚ฌ๋“œ ํŒจํ„ด์„ ์ ์šฉํ•ด์„œ ๋ฐ”๊พธ๋ฉด ์˜ค๋ฅธ์ชฝ๊ณผ ๊ฐ™์€ ๊ทธ๋ฆผ์ด ๋‚˜์˜จ๋‹ค. ํด๋ผ์ด์–ธํŠธ ํด๋ž˜์Šค๋“ค์ด ํผ์‚ฌ๋“œ๋ฅผ ํ†ตํ•ด์„œ ์„œ๋ธŒ์‹œ์Šคํ…œ์— ์ ‘๊ทผํ•˜๋„๋ก ํ•œ ๊ฒƒ์ด๋‹ค. ์ด๋•Œ ๊ผญ ํผ์‚ฌ๋“œ๋ฅผ ํ†ตํ•ด์„œ๋งŒ ์„œ๋ธŒ์‹œ์Šคํ…œ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์€ ์•„๋‹ˆ๋‹ค. ๋‹จ์ง€ ํผ์‚ฌ๋“œ๋ฅผ ํ†ตํ•ด์„œ ์„œ๋ธŒ์‹œ์Šคํ…œ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ธธ์„ ์—ด๊ณ  ๊ทธ๋ ‡๊ฒŒ ์œ ๋„๋งŒ ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ๊ฐ•์ œ์„ฑ์ด ์—†๋‹ค๋Š” ๋œป์ด๋‹ค.  

 

์ด ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜๋Š” ๋Œ€ํ‘œ์ ์ธ ์˜ˆ๊ฐ€ ์ปดํŒŒ์ผ๋Ÿฌ์ด๋‹ค. ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ๊ตฌํ˜„๋œ๋‹ค.



์œ ์šฉ์„ฑ ( Applicability ) :

Use the Facade pattern when


ยท you want to provide a simple interface to a complex subsystem. Subsystems often get more complex as they evolve. Most patterns, when applied, result in more and smaller classes. This makes the subsystem more reusable and easier to customize, but it also becomes harder to use for clients that don't need to customize it. A facade can provide a simple default view of the subsystem that is good enough for most clients. Only clients needing more customizability will need to look beyond the facade.

๋ณต์žกํ•œ ์„œ๋ธŒ์‹œ์Šคํ…œ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ„๋‹จํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉ


ยท there are many dependencies between clients and the implementation classes of an abstraction. Introduce a facade to decouple the subsystem from clients and other subsystems, thereby promoting subsystem independence and portability.

์„œ๋ธŒ์‹œ์Šคํ…œ์„ ํด๋ผ์ด์–ธํŠธ ๋˜๋Š” ๋‹ค๋ฅธ ์„œ๋ธŒ์‹œ์Šคํ…œ์œผ๋กœ๋ถ€ํ„ฐ ๋””์ปคํ”Œ์‹œํ‚ด์œผ๋กœ์จ ๋…๋ฆฝ์„ฑ๊ณผ ํœด๋Œ€์„ฑ(์ด์‹์„ฑ)์„ ๋†’์ด๊ธฐ ์œ„ํ•ด์„œ ์‚ฌ์šฉ 


ยท you want to layer your subsystems. Use a facade to define an entry point to each subsystem level. If subsystems are dependent, then you can simplify the dependencies between them by making them communicate with each other solely through their facades.


๋“ฑ์žฅ ์ธ๋ฌผ ( Participants ) :

ยท Facade (Compiler)
o knows which subsystem classes are responsible for a request.
o delegates client requests to appropriate subsystem objects.
ยท subsystem classes (Scanner, Parser, ProgramNode, etc.)
o implement subsystem functionality.
o handle work assigned by the Facade object.
o have no knowledge of the facade; that is, they keep no references to it.


์›๋ฆฌ ( Collaborations ) :

ยท Clients communicate with the subsystem by sending requests to Facade, which forwards them to the appropriate subsystem object(s). Although the subsystem objects perform the actual work, the facade may have to do work of its own to translate its interface to subsystem interfaces.

ํด๋ผ์ด์–ธํŠธ๋Š” ํผ์‚ฌ๋“œ์— ์š”์ฒญ์„ ํ•จ์œผ๋กœ์จ ๋ณต์žกํ•œ ์„œ๋ธŒ์‹œ์Šคํ…œ์— ์ ‘๊ทผํ•œ๋‹ค.
ยท Clients that use the facade don't have to access its subsystem objects directly.

ํด๋ผ์ด์–ธํŠธ๋Š” ๋ณต์žกํ•œ ์„œ๋ธŒ์‹œ์Šคํ…œ์˜ ๊ฐ์ฒด์— ์ง์ ‘์ ์œผ๋กœ ์ ‘๊ทผํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค. 


ํŒจํ„ด ์‚ฌ์šฉ์˜ ์žฅ๋‹จ์  ( Consequences ): 

 The Facade pattern offers the following benefits:


1. It shields clients from subsystem components, thereby reducing the number of objects that clients deal with and making the subsystem easier to use. ์‚ฌ์šฉ์ž๊ฐ€ ์•Œ์•„์•ผ ํ•˜๋Š” ์„œ๋ธŒ์‹œ์Šคํ…œ์˜ ๋ฒ”์œ„๋ฅผ ์ค„์—ฌ์ค€๋‹ค. 


2. It promotes weak coupling between the subsystem and its clients. 1๋ฒˆ์˜ ์ด์œ ๋กœ ์‚ฌ์šฉ์ž์™€ ์„œ๋ธŒ์‹œ์Šคํ…œ ์‚ฌ์ด์˜ ์ปคํ”Œ๋ง ๊ด€๊ณ„๋ฅผ ์•ฝํ™”์‹œ์ผœ์ค€๋‹ค. Often the components in a subsystem are strongly coupled. Weak coupling lets you vary the components of the subsystem without affecting its clients. Facades help layer a system and the dependencies between objects. They can eliminate complex or circular dependencies. This can be an important consequence when the client and the subsystem are implemented independently. Reducing compilation dependencies is vital in large software systems. You want to save time by minimizing recompilation when subsystem classes change. Reducing compilation dependencies with facades can limit the recompilation needed for a small change in an important subsystem. A facade can also simplify porting systems to other platforms, because it's less likely that building one subsystem requires building all others.


3. It doesn't prevent applications from using subsystem classes if they need to. ์‚ฌ์šฉ์ž๊ฐ€ ์›ํ•  ๋•Œ์—๋Š” ์„œ๋ธŒ์‹œ์Šคํ…œ์— ์ง์ ‘ ์ ‘๊ทผํ•˜์—ฌ ๋‚ด๋ถ€ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.Thus you can choose between ease of use and generality.

 

๊ด€๋ จ ํŒจํ„ด๋“ค : 

Abstract Factory can be used with Facade to provide an interface for creating subsystem objects in a subsystem-independent way. Abstract Factory can also be used as an alternative to Facade to hide platform-specific classes.
Mediator is similar to Facade in that it abstracts functionality of existing classes. However, Mediator's purpose is to abstract arbitrary communication between colleague objects, often centralizing functionality that doesn't belong in any one of them. A mediator's colleagues are aware of and communicate with the mediator instead of communicating with each other directly. In contrast, a facade merely abstracts the interface to subsystem objects to make them easier to use; it doesn't define new functionality, and subsystem classes don't know about it.
Usually only one Facade object is required. Thus Facade objects are often Singletons.


์ถ”๊ฐ€ ์ •๋ณด :  

  • Facade defines a new interface, whereas Adapter uses an old interface. Remember that Adapter makes two existing interfaces work together as opposed to defining an entirely new one.
  • Whereas Flyweight shows how to make lots of little objects, Facade shows how to make a single object represent an entire subsystem.
  • Mediator is similar to Facade in that it abstracts functionality of existing classes. Mediator abstracts/centralizes arbitrary communications between colleague objects. It routinely "adds value", and it is known/referenced by the colleague objects. In contrast, Facade defines a simpler interface to a subsystem, it doesn't add new functionality, and it is not known by the subsystem classes.
  • Abstract Factory can be used as an alternative to Facade to hide platform-specific classes.
  • Facade objects are often Singletons because only one Facade object is required.
  • Adapter and Facade are both wrappers; but they are different kinds of wrappers. The intent of Facade is to produce a simpler interface, and the intent of Adapter is to design to an existing interface. While Facade routinely wraps multiple objects and Adapter wraps a single object; Facade could front-end a single complex object and Adapter could wrap several legacy objects.
  • Facade pattern is more like a helper for client applications, it doesnโ€™t hide subsystem interfaces from the client. Whether to use Facade or not is completely dependent on client code.
  • Facade pattern can be applied at any point of development, usually when the number of interfaces grow and system gets complex.
  • Subsystem interfaces are not aware of Facade and they shouldnโ€™t have any reference of the Facade interface.
  • Facade pattern should be applied for similar kind of interfaces, its purpose is to provide a single interface rather than multiple interfaces that does the similar kind of jobs.
  • We can use Factory Pattern with Facade to provide better interface to client systems.

์–ด๋Œ‘ํ„ฐ ํŒจํ„ด๊ณผ ํผ์‚ฌ๋“œ ํŒจํ„ด์˜ ์ฐจ์ด์ ์€ ์–ผ๋งˆ๋‚˜ ๋งŽ์€ ํด๋ž˜์Šค๋ฅผ wrapํ•˜๋Š๋ƒ๊ฐ€ ์•„๋‹ˆ๋‹ค. Adapter ํŒจํ„ด์€ ํ•˜๋‚˜ ์ด์ƒ์˜ ํด๋ž˜์Šค๋ฅผ ๋ฌถ์–ด์„œ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์›ํ•˜๋Š” ์ถœ๋ ฅ์ด ๋‚˜์˜ค๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด๊ณ  Facade ํŒจํ„ด์€ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์‚ฌ์šฉํ•˜๊ธฐ์—๋Š” ๋ณต์žกํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ•˜๋‚˜๋กœ ๋ฌถ๊ณ  ๊ฐ„๋‹จํ•œ ์ ‘๊ทผ๊ฒฝ๋กœ๋ฅผ ์ œ๊ณตํ•จ์œผ๋กœ์จ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์†์‰ฝ๊ฒŒ ๋ณต์žกํ•œ ์ธํ„ฐํŽ˜์ด์Šค ๋‚ด๋ถ€์˜ ๊ธฐ๋Šฅ์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

 

 

 

 

์ถœ์ฒ˜ :  http://sourcemaking.com/design_patterns/facade

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

http://www.journaldev.com/1557/facade-pattern-in-java-example-tutorial

 


 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.

์ด ํŒจํ„ด๋“ค์€ ๊ฐ์ฒด๋“ค ์‚ฌ์ด์˜ ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜์— ๊ด€์‹ฌ์„ ๊ฐ€์ง„๋‹ค.

 

์˜ค๋Š˜ ์‚ดํŽด๋ณผ  Bridge ํŒจํ„ด์€ Structural ํŒจํ„ด์— ์†ํ•œ๋‹ค.  

 

๋ง๊ทธ๋Œ€๋กœ A์™€ B๋ฅผ ์—ฐ๊ฒฐํ•˜๋Š” ๋‹ค๋ฆฌ์—ญํ• ์„ ํ•˜๋Š” ํŒจํ„ด์ด๋‹ค. 

 

Bridge Pattern Structure



 


ํŒจํ„ด์˜ ๋ชฉ์  ( Intent ) : 

Decouple an abstraction from its implementation so that the two can vary independently.

๋ธŒ๋ฆฌ์ง€ ํŒจํ„ด์€ ์–ด๋Œ‘ํ„ฐ ํŒจํ„ด๊ณผ ๋น„์Šทํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ๊ทธ ๋ชฉ์ ์ด ๋ถ„๋ช…ํžˆ ๋‹ค๋ฆ„์„ ์ˆ™์ง€ํ•ด์•ผํ•œ๋‹ค. ๋ธŒ๋ฆฌ์ง€ ํŒจํ„ด์€ ์ถ”์ƒํ™”๋ฅผ ํ•จ์œผ๋กœ์จ ๋‘๊ฐœ๋ฅผ ๊ตฌ๋ถ„์ง“๊ธฐ ์œ„ํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š” ํŒจํ„ด์ด๋‹ค.

 

 

ํŒจํ„ด์ด ๋‚˜์˜ค๊ฒŒ ๋œ ๋™๊ธฐ ( Motivation ) :

When an abstraction can have one of several possible implementations, the usual way to accommodate them is to use inheritance. An abstract class defines the interface to the abstraction, and concrete subclasses implement it in different ways. But this approach isn't always flexible enough. Inheritance binds an implementation to the abstraction permanently, which makes it difficult to modify, extend, and reuse abstractions and implementations independently.
Consider the implementation of a portable Window abstraction in a user interface toolkit. This abstraction should enable us to write applications that work on both the X Window System and IBM's Presentation Manager (PM), for example. Using inheritance, we could define an abstract class Window and subclasses XWindow and PMWindow that implement the Window interface for the different platforms. But this approach has two drawbacks:


1. It's inconvenient to extend the Window abstraction to cover different kinds
of windows or new platforms. Imagine an IconWindow subclass of Window that
specializes the Window abstraction for icons. To support IconWindows for
both platforms, we have to implement two new classes, XIconWindow and
PMIconWindow. Worse, we'll have to define two classes for every kind of
window. Supporting a third platform requires yet another new Window subclass
for every kind of window.

 


2. It makes client code platform-dependent. Whenever a client creates a window, it instantiates a concrete class that has a specific implementation. For example, creating an XWindow object binds the Window abstraction to the X Window implementation, which makes the client code dependent on the X Window implementation. This, in turn, makes it harder to port the client code to other platforms.


Clients should be able to create a window without committing to a concrete implementation. Only the window implementation should depend on the platform on which the application runs.  Therefore client code should instantiate windows without mentioning specific platforms. 

 

The Bridge pattern addresses these problems by putting the Window abstraction and its implementation in separate class hierarchies. There is one class hierarchy for window interfaces (Window, IconWindow, TransientWindow) and a separate hierarchy for platform-specific window implementations, with WindowImp as its root. The XWindowImp subclass, for example, provides an implementation based on the X Window System. 

 



์œ ์šฉ์„ฑ ( Applicability ) :

Use the Bridge pattern when
ยท you want to avoid a permanent binding between an abstraction and its implementation. This might be the case, for example, when the implementation must be selected or switched at  run-time.
ยท both the abstractions and their implementations should be extensible by subclassing. In this case, the Bridge pattern lets you combine the different abstractions and implementations and extend them independently.
ยท changes in the implementation of an abstraction should have no impact on clients; that is, their code should not have to be recompiled.
ยท (C++) you want to hide the implementation of an abstraction completely from clients. In C++ the representation of a class is visible in the class interface.
ยท you have a proliferation of classes as shown earlier in the first Motivation diagram. Such a class hierarchy indicates the need for splitting an object into two parts. Rumbaugh uses the term "nested generalizations"  to refer to such class hierarchies.
ยท you want to share an implementation among multiple objects (perhaps using reference counting), and this fact should be hidden from the client. A simple example is Coplien's String class , in which multiple objects can share the same string representation (StringRep).

 

๋“ฑ์žฅ ์ธ๋ฌผ ( Participants ) :

ยท Abstraction (Window)
o defines the abstraction's interface.
o maintains a reference to an object of type Implementor.

ยท RefinedAbstraction (IconWindow)
o Extends the interface defined by Abstraction.
ยท Implementor (WindowImp)
o defines the interface for implementation classes. This interface doesn't have to correspond exactly to Abstraction's interface; in fact the two interfaces can be quite different. Typically the
Implementor interface provides only primitive operations, and Abstraction defines higher-level operations based on these primitives.

ยท ConcreteImplementor (XWindowImp, PMWindowImp)
o implements the Implementor interface and defines its concrete implementation.


 

 All operations on Window subclasses are implemented in terms of abstract operations from the WindowImp interface. This decouples the window abstractions from the various platform-specific implementations. We refer to the relationship between Window and WindowImp as a bridge,  because it bridges the abstraction and its implementation, letting them vary independently.


์›๋ฆฌ ( Collaborations ) :

ยท Abstraction forwards client requests to its Implementor object.


ํŒจํ„ด ์‚ฌ์šฉ์˜ ์žฅ๋‹จ์  ( Consequences ): 

The Bridge pattern has the following consequences:


1. Decoupling interface and implementation. An implementation is not bound permanently to an interface. The implementation of an abstraction can be configured at run-time. It's even possible for an object to change its implementation at run-time.
Decoupling Abstraction and Implementor also eliminates compile-time dependencies on the implementation. Changing an implementation class doesn't require recompiling the Abstraction class and its clients. This property is essential when you must ensure binary compatibility between different versions of a class library.
Furthermore, this decoupling encourages layering that can lead to a better-structured system. The high-level part of a system only has to know about Abstraction and Implementor. 

 

2. Improved extensibility. You can extend the Abstraction and Implementor hierarchies independently.


3. Hiding implementation details from clients. You can shield clients from implementation details, like the sharing of implementor objects and the accompanying reference count mechanism (if any).


๊ด€๋ จ ํŒจํ„ด๋“ค : 

An Abstract Factory can create and configure a particular Bridge.
The Adapter pattern
is geared toward making unrelated classes work together. It is usually applied to systems after they're designed. Bridge, on the other hand, is used up-front in a design to let abstractions and implementations vary independently.

 

์ถ”๊ฐ€ ์ •๋ณด :     

  • Adapter makes things work after they're designed; Bridge makes them work before they are.
  • Bridge is designed up-front to let the abstraction and the implementation vary independently. Adapter is retrofitted to make unrelated classes work together.
  • State, Strategy, Bridge (and to some degree Adapter) have similar solution structures. They all share elements of the "handle/body" idiom. They differ in intent - that is, they solve different problems.
  • The structure of State and Bridge are identical (except that Bridge admits hierarchies of envelope classes, whereas State allows only one). The two patterns use the same structure to solve different problems: State allows an object's behavior to change along with its state, while Bridge's intent is to decouple an abstraction from its implementation so that the two can vary independently.
  • If interface classes delegate the creation of their implementation classes (instead of creating/coupling themselves directly), then the design usually uses the Abstract Factory pattern to create the implementation objects.

 

 

 

์ถœ์ฒ˜ : http://sourcemaking.com/design_patterns/bridge

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

 


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.

์ด ํŒจํ„ด๋“ค์€ ๊ฐ์ฒด๋“ค ์‚ฌ์ด์˜ ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜์— ๊ด€์‹ฌ์„ ๊ฐ€์ง„๋‹ค.

 

์˜ค๋Š˜ ์‚ดํŽด๋ณผ  Proxy ํŒจํ„ด์€ Structural ํŒจํ„ด์— ์†ํ•œ๋‹ค.  

ํ”„ ๋ก์‹œ ํŒจํ„ด์€ ๋„คํŠธ์›Œํ‚น์„ ๊ณต๋ถ€ํ•ด๋ณธ ์‚ฌ๋žŒ์ด๋ผ๋ฉด ์ดํ•ดํ•˜๊ธฐ๊ฐ€ ์‰ฌ์šธ ๊ฒƒ์ด๋‹ค. ํ”„๋ก์‹œ๊ฐ€ ๋ญ”์ง€๋ฅผ ์•Œํ…Œ๋‹ˆ๊นŒ ๋ง์ด๋‹ค. ์—ฌ๊ธฐ์„œ ๋งํ•˜๋Š” ํ”„๋ก์‹œ๋ž€ ํ”„๋ก์‹œ ์„œ๋ฒ„์—์„œ ๋งํ•˜๋Š” ๊ทธ๊ฒƒ๊ณผ ๋™์ผํ•œ ๊ฐœ๋…์ด๋‹ค. ์ผ์ข…์˜ ์ค‘๊ฐ„์—ฐ๊ฒฐ์ž ์—ญํ• ์„ ํ•˜๋Š” ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด์„œ, ์š”์ฒญ์ด ๋“ค์–ด์˜ค๋ฉด ์ตœ์ดˆ ์š”์ฒญ์ผ ๊ฒฝ์šฐ ์ƒˆ๋กœ ์ƒ์„ฑํ•˜๊ณ  ์ƒ์„ฑ๋œ ๊ฐ์ฒด๋ฅผ ์‘๋‹ต์œผ๋กœ ๋ณด๋‚ด๊ณ , ๋‘๋ฒˆ์งธ ์š”์ฒญ๋ถ€ํ„ฐ๋Š” ๊ธฐ์กด์— ์ƒ์„ฑํ–ˆ๋˜ ๊ฒƒ์„ ์‘๋‹ต์œผ๋กœ ๋ณด๋‚ด๋Š” ๊ฒƒ์ด๋‹ค.

์ดํ•ด๊ฐ€ ์ž˜ ์•ˆ๊ฐ„๋‹ค๋ฉด ์ข€ ๋” ์ž์„ธํžˆ ์•Œ์•„๋ณด์ž. 

 

Proxy Pattern Structure

 


์šฐ์„  ์ด ํด๋ž˜์Šค ๋‹ค์ด์–ด๊ทธ๋žจ๋ถ€ํ„ฐ ์ดํ•ด๋ฅผ ํ•ด๋ณด๋„๋ก ํ•˜์ž. ์—ฌ๊ธฐ์„œ ์ค‘์š”ํ•œ ๊ฒƒ์€ RealSubject์™€ Proxy ๊ทธ๋ฆฌ๊ณ  Subject์‚ฌ์ด์˜ ๊ด€๊ณ„์ด๋‹ค. ํด๋ผ์ด์–ธํŠธ๋Š” Subject๊ฐ์ฒด์˜ Request()๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  Subject๊ฐ์ฒด๋ฅผ ๋ฐ›๋Š”๋‹ค. RealSubject์™€  Proxy๋Š” Subject๋ฅผ ์ƒ์†ํ•˜๋Š” ํด๋ž˜์Šค๋“ค์ธ๋ฐ Proxyํด๋ž˜์Šค์˜ Request()๋Š” ๊ฒฝ์šฐ์— ๋”ฐ๋ผ RealSubject์˜ Request()๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค. RealSubject์˜ Request()์—์„œ๋Š” ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์›ํ•˜๋Š” Subject๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.  

๋”ฐ๋ผ์„œ runtime์—๋Š” ํ˜ธ์ถœ ์ˆœ์„œ๊ฐ€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค๊ณ  ํ•  ์ˆ˜ ์žˆ๋‹ค. Proxy๋Š” RealSubject๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”๋ฐ ์ด๊ฒƒ์ด null์ด ์•„๋‹Œ ๊ฒฝ์šฐ ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜ํ•˜๊ณ  null์ธ๊ฒฝ์šฐ RealSubject์˜ Request()๋ฅผ ์š”์ฒญํ•˜์—ฌ ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๊ทธ๊ฒƒ์„ Proxy ๋‚ด๋ถ€์— ๊ฐ€์ง€๊ณ  ์žˆ๊ฒŒ ๋œ๋‹ค.



ํŒจํ„ด์˜ ๋ชฉ์  ( Intent ) :  


Provide a surrogate or placeholder for another object to control access to it.
ํ”„๋ก์‹œ ํŒจํ„ด์˜ ๋ชฉ์ ์€ ๋˜๋‹ค๋ฅธ ๊ฐ์ฒด์— ๋Œ€ํ•œ ์ ‘๊ทผ์„ ์ปจํŠธ๋กคํ•˜๊ธฐ ์œ„ํ•ด์„œ ๊ทธ ๊ฐ์ฒด๋ฅผ ๋‹ด์„ ์ˆ˜ ์žˆ๋Š” ๊ทธ๋ฆ‡์„ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.


ํŒจํ„ด์ด ๋‚˜์˜ค๊ฒŒ ๋œ ๋™๊ธฐ ( Motivation ) :

 

์›Œ ๋“œํ”„๋กœ๊ทธ๋žจ์—์„œ ์‚ฌ์ง„ํŒŒ์ผ์„ ๋„ฃ๊ฒŒ๋˜๋ฉด ๋กœ๋”ฉ์ด ๋Š๋ ค์ง€๋Š” ํ˜„์ƒ์ด ๋ฐœ์ƒํ•  ๋•Œ๊ฐ€ ์žˆ์—ˆ๋‹ค. ์ง€๊ธˆ์ด์•ผ ์›Œ๋‚™ ์ปดํ“จํ„ฐ ์‚ฌ์–‘์ด ์ข‹์•„์ ธ์„œ ๊ทธ๋Ÿฐ์ผ์„ ๋งŽ์ด ๋ณด์ง€๋Š” ๋ชปํ•˜์ง€๋งŒ ์‚ฌ์ง„ํŒŒ์ผ ์‚ฌ์ด์ฆˆ์—ญ์‹œ ์ข‹์€ ํ™”์งˆ์ธ ๊ฒฝ์šฐ ์ƒ๋‹นํ•œ ์‚ฌ์ด์ฆˆ๋ฅผ ์ž๋ž‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฌด์‹œํ•  ์ˆ˜ ์—†๋‹ค. ์ด๋Ÿฐ ๊ฒฝ์šฐ ํŽ˜์ด์ง€๋ฅผ ์ด๋™ํ•  ๋•Œ๋งˆ๋‹ค ๋””์Šคํฌ์— ์žˆ๋Š” ์ด๋ฏธ์ง€ ํŒŒ์ผ์„ ๊ณ„์† ์š”์ฒญํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ํ•œ๋ฒˆ๋งŒ ์š”์ฒญํ•˜์—ฌ ํ”„๋ก์‹œ์— ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๊ฐ€ ๋‹ค์‹œ ์š”์ฒญ์ด ๋“ค์–ด์˜ค๋ฉด ํ”„๋ก์‹œ์—์„œ ์ด๋ฏธ์ง€๋ฅผ ๊ฐ€์ ธ์™€์„œ ๋””์Šคํ”Œ๋ ˆ์ด ํ•ด์ฃผ๋Š” ๋ฐฉ์‹์ด ํ•„์š”ํ•˜๊ฒŒ ๋œ ๊ฒƒ์ด๋‹ค. ์ด๋Ÿฐ์‹์œผ๋กœ ์†๋„์˜ ํ–ฅ์ƒ์„ ๊ฟฐํ•œ๊ฒƒ์ด๋‹ค. ์•„๋ž˜ ๊ทธ๋ฆผ์€ ๋””์Šคํฌ์— ์žˆ๋Š” ์ด๋ฏธ์ง€ ํŒŒ์ผ์—์„œ ๋ฐ์ดํƒ€๋ฅผ ์ฝ์–ด์™€์„œ ๋ฉ”๋ชจ๋ฆฌ์— ์ƒ์ฃผํ•˜๋Š” ํ”„๋ก์‹œ์— ๋„ฃ๊ณ  ๋ฌธ์„œ์—์„œ ์ด์— ์ ‘๊ทผํ•˜๋Š” ๊ฒƒ์„ ๋ณด์—ฌ์ฃผ๊ณ ์žˆ๋‹ค.

 

์œ„์—์„œ ๋ดค๋˜ ํด๋ž˜์Šค ๋‹ค์ด์–ด๊ทธ๋žจ์— ๋ฌธ์„œํ”„๋กœ๊ทธ๋žจ์˜ ์˜ˆ๋ฅผ ์ ์šฉ์‹œ์ผœ ๋ณธ ๊ฒƒ์ด๋‹ค. ImageProxy์˜ ์šฐ์ธก์„ ๋ณด๋ฉด image๊ฐ€ 0์ธ์ง€๋ฅผ ํŒ๋ณ„ํ•˜๊ณ  0์ผ๊ฒฝ์šฐ Image๋ฅผ ๊ฐ€์ ธ์™€์„œ ๋ณด์—ฌ์ค€๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๋ ค์ฃผ๋Š” ๊ฐ„๋žตํ•œ ์†Œ์Šค๊ฐ€ ๋ณด์ธ๋‹ค.

 

 

์œ ์šฉ์„ฑ ( Applicability ) :

 

Proxy is applicable whenever there is a need for a more versatile or sophisticated reference to an object than a simple pointer. Here are several common situations in which the Proxy pattern is applicable:  

ํ”„๋ก์‹œ ํŒจํ„ด์€ ์•„๋ž˜์™€ ๊ฐ™์€ ์ƒํ™ฉ์—์„œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.


1. A remote proxy provides a local representative for an object in a different address space. NEXTSTEP [Add94] uses the class NXProxy for this purpose. Coplien [Cop92] calls this kind of proxy an "Ambassador."


2. A virtual proxy creates expensive objects on demand. The ImageProxy described in the Motivation is an example of such a proxy.


3. A protection proxy controls access to the original object. Protection proxies are useful when objects should have different access rights. For example, KernelProxies in the Choices operating system [CIRM93] provide protected access to operating system objects.


4. A smart reference is a replacement for a bare pointer that performs additional actions when an object is accessed. Typical uses include

o counting the number of references to the realobject so that it can be freed automatically when there are no more references (also called smart pointers [Ede92]).

o loading a persistent object into memory when it's first referenced.  

o checking that the realobject is locked before it's accessed to ensure that no other object can change it.

 


๋“ฑ์žฅ ์ธ๋ฌผ ( Participants ) :

โ€ข Proxy (ImageProxy) 

o maintainsareferencethatletstheproxyaccesstherealsubject.

Proxy may refer to a Subject if the RealSubject and Subject interfaces are the same.

o provides an interface identical to Subject's so that a proxy can by substituted for the real subject.

o controls access to the real subject and may be responsible for creating and deleting it.

o other responsibilities depend on the kind of proxy:

รŸ remote proxies are responsible for encoding a request and its arguments and for sending the encoded request to the real

subject in a different address space.
รŸ virtual proxies may cache additional information about the real subject so that they can postpone accessing it. For example, the ImageProxy from the Motivation caches the real image's extent.

รŸ protection proxies check that the caller has the access permissions required to perform a request.

โ€ข Subject (Graphic)

o defines the common interface for RealSubject and Proxy so that a Proxy can be used anywhere a RealSubject is expected.

โ€ข RealSubject (Image)

o defines the real object that the proxy represents.


์›๋ฆฌ ( Collaborations ) :

โ€ข Proxy forwards requests to RealSubject when appropriate, depending on the kind of proxy.


ํŒจํ„ด ์‚ฌ์šฉ์˜ ์žฅ๋‹จ์  ( Consequences ): 

 

The Proxy pattern introduces a level of indirection when accessing an object. The additional indirection has many uses, depending on the kind of proxy:

  1. A remote proxy can hide the fact that an object resides in a different address space.

  2. A virtual proxy can perform optimizations such as creating an object on demand.

  3. Both protection proxies and smart references allow additional house keeping tasks when an object is accessed.

There's another optimization that the Proxy pattern can hide from the client. It's called copy-on-write, and it's related to creation on demand. Copying a large and complicated object can be an expensive operation. If the copy is never modified, then there's no need to incur this cost. By using a proxy to postpone the copying process, we ensure that we pay the price of copying the object only if it's modified.

 

To make copy-on-write work, the subject must be reference counted. Copying the proxy will do nothing more than increment this reference count. Only when the client requests an operation that modifies the subject does the proxy actually copy it. In that case the proxy must also decrement the subject's reference count. When the reference count goes to zero, the subject gets deleted.

Copy-on-write can reduce the cost of copying heavyweight subjects significantly.

 

๊ด€๋ จ ํŒจํ„ด๋“ค : 

 

Adapter : An adapter provides a different interface to the object it adapts. In contrast, a proxy provides the same interface as its subject. However, a proxy used for access protection might refuse to perform an operation that the subject will perform, so its interface may be effectively a subset of the subject's.

Decorator : Although decorators can have similar implementations as proxies, decorators have a different purpose. A decorator adds one or more responsibilities to an object, whereas a proxy controls access to an object.

 

Proxies vary in the degree to which they are implemented like a decorator. A protection proxy might be implemented exactly like a decorator. On the other hand, a remote proxy will not contain a direct reference to its real subject but only an indirect reference, such as "host ID and local address on host." A virtual proxy will start off with an indirect reference such as a file name but will eventually obtain and use a direct reference.

 

 

์ถ”๊ฐ€ ์ •๋ณด :   

  • Adapter provides a different interface to its subject. Proxy provides the same interface. Decorator provides an enhanced interface.
  • Decorator and Proxy have different purposes but similar structures. Both describe how to provide a level of indirection to another object, and the implementations keep a reference to the object to which they forward requests.

 

 

ํ”„๋ก์‹œ ํŒจํ„ด์„ ์‚ฌ์šฉํ•œ ๊ฐ„๋‹จํ•œ ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค.

 

interface Image { public void displayImage(); } //on System A class RealImage implements Image { private String filename; public RealImage(String filename) { this.filename = filename; loadImageFromDisk(); } private void loadImageFromDisk() { System.out.println("Loading " + filename); } public void displayImage() { System.out.println("Displaying " + filename); } } //on System B class ProxyImage implements Image { private String filename; private Image image; public ProxyImage(String filename) { this.filename = filename; } public void displayImage() { if (image == null) { image = new RealImage(filename); } image.displayImage(); } } class ProxyExample { public static void main(String[] args) { Image image1 = new ProxyImage("HiRes_10MB_Photo1"); Image image2 = new ProxyImage("HiRes_10MB_Photo2"); image1.displayImage(); // loading necessary image2.displayImage(); // loading necessary
image1.displayImage(); // loading unnecessary image2.displayImage(); // loading unnecessary } }

๋˜ ๋‹ค๋ฅธ ๋ชฉ์ ( ๋ฆฌ๋ˆ…์Šค์—์„œ ๊ถŒํ•œ์— ๋”ฐ๋ผ ๋ช…๋ น์–ด ์‹คํ–‰์„ ๋ง‰๊ฑฐ๋‚˜ ํ†ต๊ณผ์‹œํ‚ค๋Š”)์œผ๋กœ ์‚ฌ์šฉ๋œ ํ”„๋ก์‹œ ํŒจํ„ด์˜ ์˜ˆ์ œ๋Š” ์•„๋ž˜ ๋งํฌ์—์„œ ๋ณด์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

http://www.journaldev.com/1572/proxy-design-pattern-in-java-example-tutorial

 



์ถœ์ฒ˜ :  http://sourcemaking.com/design_patterns/proxy

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

 http://ko.wikipedia.org/wiki/%ED%94%84%EB%A1%9D%EC%8B%9C_%ED%8C%A8%ED%84%B4


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.

์ด ํŒจํ„ด๋“ค์€ ๊ฐ์ฒด๋“ค ์‚ฌ์ด์˜ ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜์— ๊ด€์‹ฌ์„ ๊ฐ€์ง„๋‹ค.

 

์˜ค๋Š˜ ์‚ดํŽด๋ณผ  Decorator ํŒจํ„ด์€ Structural ํŒจํ„ด์— ์†ํ•œ๋‹ค.  ์ด ํŒจํ„ด์€ ์ปดํฌ์ง€ํŠธ ํŒจํ„ด๊ณผ ๋น„์Šทํ•œ ๋‹ค์ด์–ด๊ทธ๋žจ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. 

 

Decorator Pattern Structure


ํŒจํ„ด์˜ ๋ชฉ์  ( Intent ) : 

 Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.

 ๋™์ ์œผ๋กœ ๊ฐ์ฒด์— ์ฑ…์ž„(๊พธ๋ฐˆ)์„ ์ถ”๊ฐ€ํ•œ๋‹ค. ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋Š” ๊ธฐ๋Šฅ์„ ํ™•์žฅํ•˜๊ธฐ ์œ„ํ•œ subclassing์ด ์•„๋‹Œ ๋‹ค๋ฅธ ์œ ๋™์ ์ธ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•œ๋‹ค. 


ํŒจํ„ด์ด ๋‚˜์˜ค๊ฒŒ ๋œ ๋™๊ธฐ ( Motivation ) :

์ผ๋ฐ˜์ ์œผ๋กœ ๊ฐ„๋‹จํ•œ ํ”„๋กœ์ ํŠธ๊ฐ€ ์•„๋‹Œ ์ด์ƒ ํ•˜๋‚˜์˜ ํด๋ž˜์Šค ๋‚ด์—์„œ ๋ชจ๋“  ๊ฒƒ์„ ํ•ด๊ฒฐํ•˜๋Š” ์ผ์€ ๊ฑฐ์˜ ์—†๋‹ค. ์œ ์ง€๋ณด์ˆ˜๋ฅผ ์œ„ํ•ด์„œ๋ผ๋„ ๊ธฐ๋Šฅ๋ณ„๋กœ ํด๋ž˜์Šค๋ฅผ ๋‚˜๋ˆ„๊ฒŒ ๋˜๋Š”๋ฐ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ ํŒจํ„ด๋„ ์ด๋Ÿฐ ์‹์˜ ์ƒ๊ฐ์—์„œ ๋‚˜์˜ค๊ฒŒ ๋œ ๊ฒƒ์ด๋‹ค. ๊ทธ๋ž˜์„œ ์ƒ์†์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๊ธฐ๋„ ํ•˜๋Š”๋ฐ ์ด๋Š” ๋งค์šฐ ๊ธฐ๋ณธ์ ์ธ ๋ฐฉ๋ฒ•์ด๋ฉฐ flexibleํ•˜์ง€ ์•Š๊ณ  ์ •์ ์ด๋‹ค. ๋”ฐ๋ผ์„œ ๋™์ ์œผ๋กœ ๊ธฐ๋Šฅํ™•์žฅ์ด ์šฉ์ดํ•˜๋„๋ก ํ•œ ๊ฒƒ์ด ๋ฐ”๋กœ ์ด ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ ํŒจํ„ด์ด๋‹ค. ์•„๋ž˜ ๊ทธ๋ฆผ์€ TextView์— ScrollDecorator์™€ BorderDecorator๋ฅผ ์ด์šฉํ•˜์—ฌ ์ฑ…์ž„(๊พธ๋ฐˆ)์„ ์ถ”๊ฐ€ํ•œ ๊ฒฐ๊ณผ์ด๋‹ค.

 

์œ ์šฉ์„ฑ ( Applicability ) :

Use Decorator

๋ฐ์ฝ”๋ ˆ์ดํ„ฐ ํŒจํ„ด์€ ์•„๋ž˜์™€ ๊ฐ™์€ ์ƒํ™ฉ์—์„œ ์œ ์šฉํ•˜๋‹ค.


ยท to add responsibilities to individual objects dynamically and transparently, that is, without affecting other objects.

๋‹ค๋ฅธ ๊ฐ์ฒด์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š๊ณ  ๋™์ ์œผ๋กœ ํˆฌ๋ช…ํ•˜๊ฒŒ ๋…๋ฆฝ์ ์ธ ๊ฐ์ฒด๋“ค์„ ์ถ”๊ฐ€ํ•  ๋•Œ
ยท for responsibilities that can be withdrawn.

์ฒ ํšŒ๊ฐ€ ๊ฐ€๋Šฅํ•œ ์ฑ…์ž„(๊พธ๋ฐˆ)์„ ์ถ”๊ฐ€ํ•˜๊ณ  ์‹ถ์„ ๋•Œ
ยท when extension by subclassing is impractical. Sometimes a large number of independent extensions are possible and would produce an explosion of subclasses to support every combination. Or a class definition may be hidden or otherwise unavailable for subclassing. 

์„œ๋ธŒํด๋ž˜์‹ฑ์œผ๋กœ ๊ธฐ๋Šฅํ™•์žฅํ•˜๋Š” ๊ฒƒ์ด ๋น„์‹ค์šฉ์ ์ผ ๋•Œ


๋“ฑ์žฅ ์ธ๋ฌผ ( Participants ) :

ยท Component (VisualComponent)
o defines the interface for objects that can have responsibilities added to them dynamically.

๋™์ ์œผ๋กœ ์ถ”๊ฐ€๋˜๋Š” ์ฑ…์ž„์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋Š” ๊ฐ์ฒด๋ฅผ ์œ„ํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ •์˜ํ•œ๋‹ค.
ยท ConcreteComponent (TextView)
o defines an object to which additional responsibilities can be attached.

์ถ”๊ฐ€์ ์ธ ์ฑ…์ž„์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋Š” ๊ฐ์ฒด๋ฅผ ์ •์˜ํ•œ๋‹ค.
ยท Decorator
o maintains a reference to a Component object and defines an interface that conforms to Component's interface.

์ด ํŒจํ„ด์˜ ๋ฉ”์ธ์ด๋‹ค. ์ปดํฌ๋„ŒํŠธ ๊ฐ์ฒด์˜ ๋ ˆํผ๋Ÿฐ์Šค๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฉฐ, ์ปดํฌ๋„ŒํŠธ์™€ ์กฐํ™”๋ฅผ ์ด๋ฃจ๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ •์˜ํ•œ๋‹ค.
ยท ConcreteDecorator (BorderDecorator, ScrollDecorator)
o adds responsibilities to the component.

์ปดํฌ๋„ŒํŠธ์— ์ฑ…์ž„์„ ๋ถ€๊ณผํ•œ๋‹ค. 


์›๋ฆฌ ( Collaborations ) :

ยท Decorator forwards requests to its Component object. It may optionally perform additional operations before and after forwarding the request.


ํŒจํ„ด ์‚ฌ์šฉ์˜ ์žฅ๋‹จ์  ( Consequences ): 

The Decorator pattern has at least two key benefits and two liabilities:

 

1. More flexibility than static inheritance. ์ •์ ์ธ ์ƒ์†๋ณด๋‹ค ํ›จ์”ฌ ์œ ๋™์ ์ด๋‹ค. The Decorator pattern provides a more flexible way to add responsibilities to objects than can be had with static (multiple) inheritance. With decorators, responsibilities can be added and removed at run-time simply by attaching and detaching them. In contrast, inheritance requires creating a new class for each additional responsibility (e.g., BorderedScrollableTextView, BorderedTextView). This gives rise to many classes and increases the complexity of a system.
Furthermore, providing different Decorator classes for a specific Component class lets you mix and match responsibilities.
Decorators also make it easy to add a property twice. For example, to give a TextView a double border, simply attach two BorderDecorators. Inheriting from a Border class twice is error-prone at best.


2. Avoids feature-laden classes high up in the hierarchy. Decorator offers a pay-as-you-go approach to adding responsibilities. Instead of trying to support all foreseeable features in a complex, customizable class, you can define a simple class and add functionality incrementally with Decorator objects. Functionality can be composed from simple pieces. As a result, an application needn't pay for features it doesn't use. It's also easy to define new kinds of Decorators independently from the classes of objects
they extend, even for unforeseen extensions. Extending a complex class tends to expose details unrelated to the responsibilities you're adding.


3. A decorator and its component aren't identical. A decorator acts as a transparent enclosure. But from an object identity point of view, a decorated component is not identical to the component itself. Hence you shouldn't rely on object identity when you use decorators.


4. Lots of little objects. A design that uses Decorator often results in systems composed of lots of little objects that all look alike. The objects differ only in the way they are interconnected, not in their class or in the value of their variables. Although these systems are easy to customize by those who understand them, they can be hard to learn and debug. 

 

๊ด€๋ จ ํŒจํ„ด๋“ค : 

Adapter : A decorator is different from an adapter in that a decorator only changes an object's responsibilities, not its interface; an adapter will give an object a completely new interface. 

 Composite : A decorator can be viewed as a degenerate composite with only one component. However, a decorator adds additional responsibilitiesโ€”it isn't intended for object aggregation.
Strategy : A decorator lets you change the skin of an object; a strategy lets you change the guts. These are two alternative ways of changing an object.


์ถ”๊ฐ€ ์ •๋ณด :  

  • Adapter provides a different interface to its subject. Proxy provides the same interface. Decorator provides an enhanced interface.
  • Adapter changes an object's interface, Decorator enhances an object's responsibilities. Decorator is thus more transparent to the client. As a consequence, Decorator supports recursive composition, which isn't possible with pure Adapters.
  • Composite and Decorator have similar structure diagrams, reflecting the fact that both rely on recursive composition to organize an open-ended number of objects.
  • A Decorator can be viewed as a degenerate Composite with only one component. However, a Decorator adds additional responsibilities - it isn't intended for object aggregation.
  • Decorator is designed to let you add responsibilities to objects without subclassing. Composite's focus is not on embellishment but on representation. These intents are distinct but complementary. Consequently, Composite and Decorator are often used in concert.
  • Composite could use Chain of Responsibility to let components access global properties through their parent. It could also use Decorator to override these properties on parts of the composition.
  • Decorator and Proxy have different purposes but similar structures. Both describe how to provide a level of indirection to another object, and the implementations keep a reference to the object to which they forward requests.
  • Decorator lets you change the skin of an object. Strategy lets you change the guts.
  • Decorator pattern is helpful in providing runtime modification abilities and hence more flexible. Its easy to maintain and extend when the number of choices are more.
  • The disadvantage of decorator pattern is that it uses a lot of similar kind of objects (decorators).
    ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ ํŒจํ„ด์˜ ๋‹จ์ ์€ ์œ ์‚ฌํ•œ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ ๊ฐ์ฒด๊ฐ€ ๋งŽ์•„์งˆ ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ด๋‹ค.
  • Decorator pattern is used a lot in Java IO classes, such as FileReader, BufferedReader etc.
    ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ ํŒจํ„ด์€ FileReader๋‚˜ BufferedReader์™€ ๊ฐ™์€ Java IO ํด๋ž˜์Šค๋“ค์—์„œ ๋งŽ์ด ์‚ฌ์šฉ๋˜๊ณ  ์žˆ๋‹ค.

 

์ถœ์ฒ˜ :  http://sourcemaking.com/design_patterns/decorator

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

http://www.journaldev.com/1540/decorator-pattern-in-java-example-tutorial

 

 

 

์‹ค์ƒํ™œ์„ ์˜ˆ๋กœ ๋“  ์ข‹์€ ์˜ˆ์ œ๋Š” ์•„๋ž˜์—์„œ ํ™•์ธํ•˜๊ธฐ ๋ฐ”๋ž€๋‹ค.

http://warmz.tistory.com/757


 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.

์ด ํŒจํ„ด๋“ค์€ ๊ฐ์ฒด๋“ค ์‚ฌ์ด์˜ ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜์— ๊ด€์‹ฌ์„ ๊ฐ€์ง„๋‹ค.

 

์˜ค๋Š˜ ์‚ดํŽด๋ณผ  Adapter ํŒจํ„ด์€ Structural ํŒจํ„ด์— ์†ํ•œ๋‹ค.  

 

์–ด ๋Œ‘ํ„ฐ๊ฐ€ ๋ญ๋ƒ? ์šฐ๋ฆฌ๊ฐ€ ๋งจ๋‚  ์“ฐ๋Š” ๊ทธ ์–ด๋Œ‘ํ„ฐ๊ฐ€ ๋ฐ”๋กœ ์ง€๊ธˆ ๋งํ•˜๊ณ ์žํ•˜๋Š” ์–ด๋Œ‘ํ„ฐ์ด๋‹ค. ์–ด๋Œ‘ํ„ฐ์˜ ์—ญํ• ์ด ๋ญ๋ƒ? ์„œ๋กœ ๋งž๋ฌผ๋ฆฌ์ง€ ์•Š๋Š” ๋‘๊ฐœ์˜ ๊ฐ์ฒด๋ฅผ ์—ฐ๊ฒฐ์‹œ์ผœ์ฃผ๋Š” ์ผ์„ ํ•˜๋Š” ๊ฒƒ์ด ์–ด๋Œ‘ํ„ฐ์˜ ์—ญํ• ์ด๋‹ค. ์ด ์ƒ๊ฐ์„ ๊ฐ€์ง€๊ณ  ์•„๋ž˜ ๋‚ด์šฉ์„ ํ›‘์–ด๋ณด๊ธฐ ๋ฐ”๋ž€๋‹ค.

 

Adapter Pattern Structure

 A class adapter uses multiple inheritance to adapt one interface to another:

ํด๋ž˜์Šค ์–ด๋Œ‘ํ„ฐ๋Š” ํ•˜๋‚˜์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋‹ค๋ฅธ ์ธํ„ฐํŽ˜์ด์Šค์™€ ์—ฐ๊ฒฐ์‹œํ‚ค๊ธฐ ์œ„ํ•ด์„œ ๋‹ค์ค‘์ƒ์†์„ ์ด์šฉํ•œ๋‹ค.

 

 

An object adapter relies on object composition:

๊ฐ์ฒด ์–ด๋Œ‘ํ„ฐ๋Š” ๊ฐ์ฒด์˜ ๊ตฌ์„ฑ์— ์˜์กดํ•œ๋‹ค. ( ๋ญ” ๋ง์ธ์ง€ ๋ชจ๋ฅด๊ฒ ๋‹ค ์ผ๋‹จ ๋„˜์–ด๊ฐ€์ž )



 

ํŒจํ„ด์˜ ๋ชฉ์  ( Intent ) : 

Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.

์–ด๋Œ‘ํ„ฐ ํŒจํ„ด์˜ ๋ชฉ์ ์€ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์›ํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด์„œ ํด๋ž˜์Šค์˜ ํ˜•ํƒœ๋ฅผ ๋ณ€ํ˜•ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.(์ด๋Š” ์„œ๋กœ ์—ฐ๊ฒฐ์„ ์‹œ์ผœ์คŒ์œผ๋กœ์จ ์•„์›ƒํ’‹์„ ๋ณ€ํ˜•ํ•œ๋‹ค๋Š” ์˜๋ฏธ์ด์ง€ ์‹ค์ œ๋กœ ๋ณ€ํ˜•ํ•œ๋‹ค๋Š” ์˜๋ฏธ๊ฐ€ ์•„๋‹ˆ๋‹ค) ์–ด๋Œ‘ํ„ฐ๋Š” ์„œ๋กœ ๋งž๋ฌผ๋ฆฌ์ง€ ์•Š๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋“ค์„ ์„œ๋กœ ์—ฐ๊ฒฐ์‹œ์ผœ์ฃผ๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

 

 

ํŒจํ„ด์ด ๋‚˜์˜ค๊ฒŒ ๋œ ๋™๊ธฐ ( Motivation ) :

์˜ˆ ๋ฅผ ๋“ค์–ด ์ด๋Ÿฐ ๊ฒฝ์šฐ๊ฐ€ ์žˆ์„ ๊ฒƒ์ด๋‹ค. ๊ณ ๊ฐ์ด ์›ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„์„ ํ–ˆ๋‹ค๊ณ  ํ•˜์ž. ์ด ๊ธฐ๋Šฅ์€ ์ธํ’‹์œผ๋กœ A๊ฐ์ฒด๋ฅผ ๋ฐ›์•„๋“ค์ด๊ณ  ์•„์›ƒํ’‹์œผ๋กœ X๊ฐ์ฒด๋ฅผ ๋˜์ง€๋ฉฐ ๊ณ ๊ฐ์ด ๋งŒ๋“  API์™€ ์—ฐ๊ฒฐ์ด ๋œ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์–ผ๋งˆ๊ฐ€ ์ง€๋‚˜์„œ ๊ณ ๊ฐ์ด ์ธํ’‹์œผ๋กœ Y๊ฐ์ฒด๋ฅผ ๋‹ฌ๋ผ๊ณ  ํ•œ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์ „์— ๋งŒ๋“ค์–ด ์คฌ๋˜ ๊ธฐ๋Šฅ์˜ ์ผ๋ถ€๋ถ„๋งŒ Y๊ฐ์ฒด๋ฅผ ์•„์›ƒํ’‹์œผ๋กœ ๋‚ด๋ณด๋‚ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ๋‹น์‹ ์ด๋ผ๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด๊ฒฐํ•  ๊ฒƒ์ธ๊ฐ€? ๋ฌผ๋ก  ์ƒ๊ฐํ•ด์•ผํ•  ์ธ์ž๋“ค์ด ๋ฌด์ˆ˜ํžˆ ๋งŽ์„ ๊ฒƒ์ด๊ณ  ๊ทธ๊ฒƒ๋“ค์— ๋”ฐ๋ผ ํ•ด๊ฒฐ์ฑ…๋„ ๋‹ค๋ฅผ ๊ฒƒ์ด๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” ๊ทธ ์ค‘ ํ•˜๋‚˜์˜ ํ•ด๊ฒฐ์ฑ…์œผ๋กœ ์–ด๋Œ‘ํ„ฐ ํŒจํ„ด์„ ๋งํ•˜๊ณ ์ž ํ•œ๋‹ค. A -> DoSomething -> X ๊ธฐ๋Šฅ์„ ํ•˜๋Š” ๊ธฐ๋Šฅ์€ ์—ฌ์ „ํžˆ ์กด์žฌํ•ด์•ผ๋งŒ ํ•˜๋ฉฐ DoSomething -> Y ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•ด์•ผํ•œ๋‹ค. ํ•˜์ง€๋งŒ ์ด ๋‘๊ฐ€์ง€๋Š” ์—„์—ฐํžˆ ๋™์ผํ•œ ๊ธฐ๋Šฅ์„ ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•œ๋‹ค. ์–ด๋Œ‘ํ„ฐ ํŒจํ„ด์„ ์ด์šฉํ•ด์•ผํ•˜๋‹ˆ๊นŒ. ๊ทธ๋Ÿฌ๋ฉด ์šฐ๋ฆฌ๋Š” A -> DoSomething -> X -> Y ๊ฐ€ ๋  ์ˆ˜ ์žˆ๊ฒŒ๋” X -> Y ๊ธฐ๋Šฅ์„ ํ•˜๋Š” ์–ด๋Œ‘ํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด ๋œ๋‹ค.

 

์‰ฝ๊ฒŒ๋งํ•˜์ž๋ฉด์†Œ์ผ“์— ๋งž๋Š” ์–ด๋Œ‘ํ„ฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์•„๋ž˜ ๊ทธ๋ฆผ์ฒ˜๋Ÿผ ๋ง์ด๋‹ค.


 

 


์œ ์šฉ์„ฑ ( Applicability ) :

Use the Adapter pattern when
ยท you want to use an existing class, and its interface does not match the one you need.

๊ธฐ์กด์˜ ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์ง€๋งŒ ๋‚ด๊ฐ€ ํ•„์š”๋กœ ํ•˜๋Š” ํ˜•ํƒœ๊ฐ€ ์•„๋‹๋•Œ
ยท you want to create a reusable class that cooperates with unrelated or unforeseen classes, that is, classes that don't necessarily have compatible interfaces.

ํŠน์ • ํ˜ธํ™˜์„ฑ์„ ๊ฐ€์ง„ ํด๋ž˜์Šค๊ฐ€ ์•„๋‹Œ ๊ด‘๋ฒ”์œ„ํ•œ ํ˜ธํ™˜์„ฑ์„ ๊ฐ€์ง„ ์žฌ์‚ฌ์šฉ๊ฐ€๋Šฅํ•œ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค๊ณ  ์‹ถ์„๋•Œ
ยท (object adapter only) you need to use several existing subclasses, but it's impractical to adapt their interface by subclassing every one. An object adapter can adapt the interface of its parent class.

 

๋“ฑ์žฅ ์ธ๋ฌผ ( Participants ) :

ยท Target (Shape)o defines the domain-specific interface that Client uses.
ยท Client (DrawingEditor)
o collaborates with objects conforming to the Target interface.
ยท Adaptee (TextView)
o defines an existing interface that needs adapting.
ยท Adapter (TextShape)
o adapts the interface of Adaptee to the Target interface.

 

์›๋ฆฌ ( Collaborations ) : 

ยท Clients call operations on an Adapter instance. In turn, the adapter calls Adaptee operations that carry out the request.


ํŒจํ„ด ์‚ฌ์šฉ์˜ ์žฅ๋‹จ์  ( Consequences ): 


Class and object adapters have different trade-offs.  

ํด๋ž˜์Šค ์–ด๋Œ‘ํ„ฐ์™€ ๊ฐ์ฒด์–ด๋Œ‘ํ„ฐ๋Š” ์„œ๋กœ์˜ ์žฅ๋‹จ์ ์ด ์žˆ๋‹ค.  

A class adapter  

ยท adapts Adaptee to Target by committing to a concrete Adapter class. As a consequence, a class adapter won't work when we want to adapt a class and all its subclasses.

ยท lets Adapter override some of Adaptee's behavior, since Adapter is a subclass of Adaptee.
ยท introduces only one object, and no additional pointer indirection is needed to get to the adaptee.

 

An object adapter
ยท lets a single Adapter work with many Adapteesโ€”that is, the Adaptee itself and all of its subclasses (if any). The Adapter can also add functionality to all Adaptees at once.
ยท makes it harder to override Adaptee behavior. It will require subclassing Adaptee and making Adapter refer to the subclass rather than the Adaptee itself.


๊ด€๋ จ ํŒจํ„ด๋“ค : 

Bridge has a structure similar to an object adapter, but Bridge has a different intent: It is meant to separate an interface from its implementation so that they can be varied easily and  independently. An adapter is meant to change the interface of an existing object.
Decorator
enhances another object without changing its interface. A decorator is thus more transparent to the application than an adapter is. As a consequence, Decorator supports  recursive composition, which isn't possible with pure adapters.
Proxy
defines a representative or surrogate for another object and does not change its interface.

 

์ถ”๊ฐ€ ์ •๋ณด :     

  • Adapter makes things work after they're designed; Bridge makes them work before they are.
  • Bridge is designed up-front to let the abstraction and the implementation vary independently. Adapter is retrofitted to make unrelated classes work together.
  • Adapter provides a different interface to its subject. Proxy provides the same interface. Decorator provides an enhanced interface.
  • Adapter is meant to change the interface of an existing object. Decorator enhances another object without changing its interface. Decorator is thus more transparent to the application than an adapter is. As a consequence, Decorator supports recursive composition, which isn't possible with pure Adapters.
  • Facade defines a new interface, whereas Adapter reuses an old interface. Remember that Adapter makes two existing interfaces work together as opposed to defining an entirely new one.

 

 

 

์ถœ์ฒ˜ : http://sourcemaking.com/design_patterns/adapter

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


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 )  


 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.

์ด ํŒจํ„ด๋“ค์€ ๊ฐ์ฒด๋“ค ์‚ฌ์ด์˜ ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜์— ๊ด€์‹ฌ์„ ๊ฐ€์ง„๋‹ค.

 

์˜ค๋Š˜ ์‚ดํŽด๋ณผ  Visitor ํŒจํ„ด์€ Behavioral ํŒจํ„ด์— ์†ํ•œ๋‹ค.  

 


 

Visitor Pattern Structure

 


 


ํŒจํ„ด์˜ ๋ชฉ์  ( Intent ) : 

Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.

 

 

ํŒจํ„ด์ด ๋‚˜์˜ค๊ฒŒ ๋œ ๋™๊ธฐ ( Motivation ) :

Consider a compiler that represents programs as abstract syntax trees. It will need to perform operations on abstract syntax trees for "static semantic" analyses like checking that all variables are defined. Itwill also need to generate code. So it might define operations for type-checking, code optimization, flow analysis, checking for variables being assigned values before they're used, and so on.
Moreover, we could use the abstract syntax trees for pretty-printing, program restructuring, code instrumentation, and computing various metrics of aprogram.
Most of these operations will need to treat nodes that represent assignment statements differently from nodes that represent variables orarithmetic expressions. Hence there will be one class for assignment statements, another for variable accesses, another for arithmetic expressions, and so on. The set of node classes depends on the language being compiled, of course, but it doesn't change much for a given language.


 


 This diagram shows part of the Node class hierarchy. The problem here is that distributing all these operations across the various node classes leads to a system that's hard to understand, maintain, and change. It will be confusing to have type-checking code mixed with pretty-printing code or flow analysis code. Moreover, adding a new operation usually requires recompiling all of these classes. It would be better if each new operation could be added separately, and the node classes were independent of the operations that apply to them.
We can have both by packaging related operations from each class in a separate object, called a visitor, and passing it to elements of the abstract syntax tree as it's traversed. When an  element "accepts" the visitor, it sends a request to the visitor that encodes the element's class. It also includes the element as an argument. The visitor will then execute the operation for that element โ€”the operation that used to be in the class of the element.

 

For example, a compiler that didn't use visitors might type-check a procedure by calling the TypeCheck operation on its abstract syntax tree. Each of the nodes would implement TypeCheck by calling TypeCheck on its components (see the preceding class diagram). If the compiler type-checked a procedure using visitors, then it would create a TypeCheckingVisitor object and call the Accept operation on the abstract syntax tree with that object as an argument. Each of the nodes would implement Accept by calling back on the visitor: anassignment node calls
VisitAssignment operation on the visitor, while a variable reference calls VisitVariableReference. What used to be the TypeCheck operation in class AssignmentNode is now the VisitAssignment operation on TypeCheckingVisitor.  

To make visitors work for more than just type-checking, we need an abstract parent class NodeVisitor for all visitors of an abstract syntax tree. NodeVisitor must declare an operation for each node class. An application that needs to compute program metrics will define new subclasses of NodeVisitor and will no longer need to add application-specific code to the node classes. The Visitor pattern encapsulates the operations for each compilation phase in a Visitor associated with that phase.

 





  

With the Visitor pattern, you define two class hierarchies: one for the elements being operated on (the Node hierarchy) and one for the visitors that define operations on the elements (the  NodeVisitor hierarchy). You create a new operation by adding a new subclass to the visitor class hierarchy. As long as the grammar that the compiler accepts doesn't change (that is, we don't have to add new Node subclasses), we can add new functionality simply by defining new NodeVisitor subclasses.

 

 

์œ ์šฉ์„ฑ ( Applicability ) :

Use the Visitor pattern when

Visitor ํŒจํ„ด์€ ์ด๋Ÿด๋•Œ ์‚ฌ์šฉํ•˜์ž!!


ยท an object structure contains many classes of objects with differing interfaces, and you want to  perform operations on these objects that depend on their concrete classes.
ยท many distinct and unrelated operations need to be performed on objects in an object structure, and you want to avoid "polluting" their classes with these operations. Visitor lets you keep related operations together by defining them in one class. When the object structure is shared by many applications, use Visitor to put operations in just those applications that need them.
ยท the classes defining the object structure rarely change, but you often want to define new operations over the structure. Changing the object structure classes requires redefining the interface to all visitors,which is potentially costly. If the object structure classes change often, then it's probably better to define the operations in those classes.

 

 

๋“ฑ์žฅ ์ธ๋ฌผ ( Participants ) :
ยท Visitor (NodeVisitor)
o declares a Visit operation for each class of ConcreteElement in the object structure. The operation's name and signature identifies the class that sends the Visit request to the visitor. That lets the visitor determine the concrete class of the element being visited. Then the visitor can access the element directly through its particular interface.


ยท ConcreteVisitor (TypeCheckingVisitor)
o implements each operation declared by Visitor. Each operation implements a fragment of the algorithm defined for the corresponding class of object in the structure. ConcreteVisitor provides the context for the algorithm and stores its local state. This state often accumulates results during the traversal of the structure.


ยท Element (Node)
o defines an Accept operation that takes a visitor as an argument.


ยท ConcreteElement (AssignmentNode,VariableRefNode)
o implements an Accept operation that takes a visitor as an argument.


ยท ObjectStructure (Program)
o can enumerate its elements.
o may provide a high-level interface to allow the visitor to visit its elements.
o may either be a composite (see Composite ) or a collection such as a list or a set.

 

์›๋ฆฌ ( Collaborations ) :

ยท A client that uses the Visitor pattern must create a ConcreteVisitor object and then traverse the object structure, visiting each element with the visitor.
ยท When an element is visited, it calls the Visitor operation that corresponds to its class. The element supplies itself as an argument to this operation to let the visitor access its state, if necessary.
The following interaction diagram illustrates the collaborations between an object structure, a visitor, and two elements:





ํŒจํ„ด ์‚ฌ์šฉ์˜ ์žฅ๋‹จ์  ( Consequences ): 


Some of the benefits and liabilities of the Visitor pattern are as follows:


1. Visitor makes adding new operations easy. Visitors make it easy to add operations that depend on the components ofcomplex objects. You can define a new operation over an object  structure simply by adding a new visitor.
In contrast, if you spread functionality over many classes, then you must change each class to  define a newoperation.

2. A visitor gathers related operations and separates unrelated ones. Related behavior isn't spread over the classes defining the object structure; it's localized in a visitor. Unrelated sets of behavior are partitioned in their own visitor subclasses. That simplifies both the classes defining the elements and the algorithms defined in the visitors. Any algorithm-specific
data structures can be hidden in thevisitor.


3. Adding new ConcreteElement classes is hard. The Visitor pattern makes it hard to add new subclasses of Element. Each new ConcreteElement gives rise to a new abstract operation on Visitor and a corresponding implementation in every ConcreteVisitor class. Sometimes a default implementation can be provided in Visitor that can be inherited by most of the ConcreteVisitors, but this is the exception rather than the rule. So the key consideration in applying the Visitor pattern is whether you are mostly likely to change the algorithm applied over an object structure or the classes of objects that make up the structure. TheVisitor class hierarchy can be difficult to maintain when new ConcreteElement classes are added frequently. In such cases, it's probably easier just to define operations on the classes that make up the structure. If the Element class hierarchy is stable, but you are continually adding operations or changing algorithms, then the Visitor pattern will help you manage the changes.


4. Visiting across class hierarchies. An iterator (see Iterator ) can visit the objects in a structure as it traverses them by calling their operations. But an iterator can't work across object structures with different types of elements.  


5. Accumulating state. Visitors can accumulate state as they visit each element in the object structure. Without a visitor, this state would be passed as extra arguments to the operations that perform the traversal, or they might appear as global variables.


6. Breaking encapsulation. Visitor's approach assumes that the ConcreteElement interface is powerful enough to let visitors do their job.
As a result, the pattern oftenforces you to provide public operations that
access an element's internal state, which may compromise its encapsulation.


๊ด€๋ จ ํŒจํ„ด๋“ค : 

Composite :Visitors can be used to apply an operation over an object structure defined by the Composite pattern.
Interpreter
:Visitor may be applied to do the interpretation.

 

์ถ”๊ฐ€ ์ •๋ณด :     

  • The abstract syntax tree of Interpreter is a Composite (therefore Iterator and Visitor are also applicable).
  • Iterator can traverse a Composite. Visitor can apply an operation over a Composite.
  • The Visitor pattern is like a more powerful Command pattern because the visitor may initiate whatever is appropriate for the kind of object it encounters.
  • The Visitor pattern is the classic technique for recovering lost type information without resorting to dynamic casts.

 

 

 

์ถœ์ฒ˜ : http://sourcemaking.com/design_patterns/visitor

         Design Patterns : Element of Reusab

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.

์ด ํŒจํ„ด๋“ค์€ ๊ฐ์ฒด๋“ค ์‚ฌ์ด์˜ ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜์— ๊ด€์‹ฌ์„ ๊ฐ€์ง„๋‹ค.

 

์˜ค๋Š˜ ์‚ดํŽด๋ณผ  Builder ํŒจํ„ด์€ Creational ํŒจํ„ด์— ์†ํ•œ๋‹ค.   


๋นŒ๋” ํŒจํ„ด์€ ํŒฉํ† ๋ฆฌ ๋ฉ”์†Œ๋“œ ๋˜๋Š” ์ถ”์ƒ ํŒฉํ† ๋ฆฌ ํŒจํ„ด์˜ ๋ฌธ์ œ์ ์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋‚˜์˜จ ํŒจํ„ด์ด๋‹ค. ํŒฉํ† ๋ฆฌ ๋ฉ”์†Œ๋“œ ๋˜๋Š” ์ถ”์ƒ ํŒฉํ† ๋ฆฌ ํŒจํ„ด์—๋Š” ๊ฐ์ฒด๊ฐ€ ๋งŽ์€ ์†์„ฑ์„ ๊ฐ€์ง€๊ณ  ์žˆ์„ ๊ฒฝ์šฐ ๋‘๊ฐ€์ง€ ์ค‘์š”ํ•œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. 

 

์ฒซ ์งธ๋กœ, ํด๋ผ์ด์–ธํŠธ๊ฐ€ ํŒฉํ† ๋ฆฌ ํด๋ž˜์Šค๋กœ ๋„˜๊ฒจ์ฃผ๋Š” ์ธ์ž๊ฐ€ ๋งŽ์•„์ง€๊ฒŒ๋˜๋ฉด( ํŒฉํ† ๋ฆฌ๊ฐ€ ๋งŽ์€ ์†์„ฑ์„ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฉด ์ด์— ๋Œ€ํ•ด ์„ค์ •์„ ํ•˜๊ธฐ์œ„ํ•ด ๋งŽ์€ ์ธ์ž๋ฅผ ๋ฐ›์•„์•ผ ํ•œ๋‹ค ) ์ž˜๋ชป๋œ ์ธ์ž๋ฅผ ๋„˜๊ฒจ์ฃผ๋Š” ์ผ๋„ ๋นˆ๋ฒˆํ•˜๊ฒŒ ์ผ์–ด๋‚  ๋ฟ ์•„๋‹ˆ๋ผ ๊ด€๋ฆฌํ•˜๊ธฐ๋„ ํž˜๋“ค์–ด์ง„๋‹ค.

๋‘˜์งธ๋กœ, ๋ช‡๋ช‡ ์ธ์ž๋“ค์€ optional์ผ ์ˆ˜ ์žˆ์ง€๋งŒ ํŒฉํ† ๋ฆฌ ํŒจํ„ด์—์„œ๋Š” ๋ชจ๋“  ์ธ์ž๋ฅผ ๋„˜๊ฒจ์ฃผ์–ด์•ผ ํ•œ๋‹ค. ( optional ์ธ์ž๋Š” null๋กœ ๋„˜๊ธด๋‹ค. ์ด๊ฑด ๊ท€์ฐฎ์€ ์ผ์ด๋‹ค. )

 

๋นŒ๋” ํŒจํ„ด์€ ๋‹จ๊ณ„๋ณ„๋กœ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๋งˆ์ง€๋ง‰ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ ์ œ๊ณตํ•จ์œผ๋กœ์จ ์œ„์™€ ๊ฐ™์€ ๋ฌธ์ œ๋“ค์„ ํ•ด๊ฒฐํ•ด์ค€๋‹ค. 


 

Builder Pattern Structure



 


ํŒจํ„ด์˜ ๋ชฉ์  ( Intent ) : 

Separate the construction of a complex object from its representation so that the same construction process can create different representations.

 ๋ณตํ•ฉ ๊ฐ์ฒด์˜ ์ƒ์„ฑ ๊ณผ์ •๊ณผ ํ‘œํ˜„ ๋ฐฉ๋ฒ•์„ ๋ถ„๋ฆฌํ•˜์—ฌ ๋™์ผํ•œ ์ƒ์„ฑ ์ ˆ์ฐจ์—์„œ ์„œ๋กœ ๋‹ค๋ฅธ ํ‘œํ˜„ ๊ฒฐ๊ณผ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ํŒจํ„ด


ํŒจํ„ด์ด ๋‚˜์˜ค๊ฒŒ ๋œ ๋™๊ธฐ ( Motivation ) :


 

์˜ˆ ๋ฅผ๋“ค์–ด RTFํฌ๋งท ํ˜•ํƒœ์˜ ํŒŒ์ผ์„ ASCIIText๋‚˜ TeXText ๋˜๋Š” ๋‹ค๋ฅธ TextWidget์˜ ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ๋งŒ๋“ ๋‹ค๊ณ  ํ•˜์ž. ์ด๋•Œ ๋ณ€ํ™˜๋˜์–ด ๋‚˜์˜ค๋Š” ํฌ๋งท์„ ์‰ฝ๊ฒŒ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•  ๊ฒƒ์ด๋‹ค. ๊ทธ๋ž˜์„œ ๋‚˜์˜จ ํŒจํ„ด์ด ๋ฐ”๋กœ ์ด ๋นŒ๋” ํŒจํ„ด์ด๋‹ค. ์œ„ ๋‹ค์ด์–ด๊ทธ๋žจ์—์„œ ๊ฐ๊ฐ์˜ ์ปจ๋ฒ„ํ„ฐ ํด๋ž˜์Šค๋“ค์€ ๋ชจ๋‘ builder์ด๋ฉฐ reader๋Š” director๋ผ ํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ณ€ํ˜•๋˜์–ด ๋‚˜์˜ค๋Š” Text๊ฐ์ฒด๋“ค์€ product๋ผ๊ณ  ๋ณด๋ฉด ๋œ๋‹ค. 

 


์œ ์šฉ์„ฑ ( Applicability ) :

Use the Builder pattern when
ยท the algorithm for creating a complex object should be independent of the parts that make up the object and how they're assembled.
ยท the construction process must allow different representations for the object that's constructed.

 

๋“ฑ์žฅ ์ธ๋ฌผ ( Participants ) : 

ยท Builder
o specifies an abstract interface for creating parts of a Product object.
ยท ConcreteBuilder
o constructs and assembles parts of the product by implementing the Builder interface.
o defines and keeps track of the representation it creates.
o provides an interface for retrieving the product.
ยท Director
o constructs an object using the Builder interface.
ยท Product
o represents the complex object under construction. ConcreteBuilder builds the product's internal representation and defines the process by which it's assembled.
o includes classes that define the constituent parts, including interfaces for assembling the parts into the final result.


์›๋ฆฌ ( Collaborations ) :

ยท The client creates the Director object and configures it with the desired Builder object.
ยท Director notifies the builder whenever a part of the product should be built.
ยท Builder handles requests from the director and adds parts to the product.
ยท The client retrieves the product from the builder.

 

The following interaction diagram illustrates how Builder and Director cooperate with a client.

 

 


ํŒจํ„ด ์‚ฌ์šฉ์˜ ์žฅ๋‹จ์  ( Consequences ): 

Here are key consequences of the Builder pattern:


1. It lets you vary a product's internal representation. The Builder object provides the director with an abstract interface for constructing the product. The interface lets the builder hide the representation and internal structure of the product. It also hides how the product gets assembled. Because the product is constructed through an abstract interface, all you have to do to change the product's internal representation is define a new kind of builder.


2. It isolates code for construction and representation. The Builder pattern improves modularity by encapsulating the way a complex object is constructed and represented. Clients needn't know anything about the classes that define the product's internal structure; such classes don't appear in Builder's interface. Each ConcreteBuilder contains all the code to create and assemble a particular kind of product. The code is written once; then different Directors can reuse it to build Product variants from the same set of parts.
In the earlier RTF example, we could define a reader for a format other than RTF, say, an SGMLReader, and use the same TextConverters to generate ASCIIText, TeXText, and TextWidget renditions of SGML documents.


3. It gives you finer control over the construction process. Unlike creational patterns that construct products in one shot, the Builder pattern constructs the product step by step under the director's control. Only when the product is finished does the director retrieve it from the builder. Hence the Builder interface reflects the process of constructing the product more than other creational patterns. This gives you finer control over the construction process and consequently the internal structure of the resulting product. 

 

๊ด€๋ จ ํŒจํ„ด๋“ค : 

 Abstract Factory is similar to Builder in that it โ€‹constructs too may complex objects. The primary difference is that the Builder pattern focuses on constructing a complex object step by step. Abstract Factory's emphasis is on families of product objects (either simple or complex). Builder returns the product as a final step, but as far as the Abstract Factory pattern is concerned, the product gets returned immediately.
A Composite is what the builder often builds.

 

์ถ”๊ฐ€ ์ •๋ณด :     

  • Sometimes creational patterns are complementory: Builder can use one of the other patterns to implement which components get built. Abstract Factory, Builder, and Prototype can use Singleton in their implementations.
  • Builder focuses on constructing a complex object step by step. Abstract Factory emphasizes a family of product objects (either simple or complex). Builder returns the product as a final step, but as far as the Abstract Factory is concerned, the product gets returned immediately.
  • Builder often builds a Composite.
  • Often, designs start out using Factory Method (less complicated, more customizable, subclasses proliferate) and evolve toward Abstract Factory, Prototype, or Builder (more flexible, more complex) as the designer discovers where more flexibility is needed.

 

 

์ถœ์ฒ˜ :  http://sourcemaking.com/design_patterns/builder

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

http://www.journaldev.com/1425/builder-design-pattern-in-java

 


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.

์ด ํŒจํ„ด๋“ค์€ ๊ฐ์ฒด๋“ค ์‚ฌ์ด์˜ ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜์— ๊ด€์‹ฌ์„ ๊ฐ€์ง„๋‹ค.

 

์˜ค๋Š˜ ์‚ดํŽด๋ณผ  Flyweight ํŒจํ„ด์€ Structural ํŒจํ„ด์— ์†ํ•œ๋‹ค.  

 

์ด ํŒจํ„ด์„ ์ ์šฉํ•ด์•ผ ํ•˜๋Š” ์ƒํ™ฉ์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

1. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ์ƒ์„ฑ๋˜๋Š” ๊ฐ์ฒด์˜ ์ˆ˜๊ฐ€ ์—„์ฒญ๋‚˜๊ฒŒ ํด ๋•Œ

2. ๊ฐ์ฒด์˜ ์ƒ์„ฑ์ด ๋ฉ”๋ชจ๋ฆฌ์— ๋งŽ์€ ๋ถ€ํ•˜๋ฅผ ์ฃผ๊ณ  ์‹œ๊ฐ„์ด ์˜ค๋ž˜ ๊ฑธ๋ฆด ๋•Œ


์ข€ ๋” ์ž์„ธํžˆ ์ด ํŒจํ„ด์— ๋Œ€ํ•ด์„œ ์งš์–ด๋ณด์ž.

 

Flyweight Pattern Structure

  


 
The following object diagram shows how flyweights are shared:

 

 


ํŒจํ„ด์˜ ๋ชฉ์  ( Intent ) : 

Use sharing to support large numbers of fine-grained objects efficiently.

ํ”Œ๋ผ์ด์›จ์ดํŠธ ํŒจํ„ด์€ ๋งŽ์€ ์ˆ˜์˜ ๊ฐ์ฒด๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์ œ๊ณตํ•˜๊ธฐ์œ„ํ•ด ๊ณต์œ ๊ฐœ๋…์„ ์ด์šฉํ•œ๋‹ค.  

 

ํŒจํ„ด์ด ๋‚˜์˜ค๊ฒŒ ๋œ ๋™๊ธฐ ( Motivation ) :

 Flyweight ํŒจํ„ด์€ ๋™์ผํ•œ ํด๋ž˜์Šค์— ๋Œ€ํ•œ ๋งŽ์€ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด์•ผ ํ•  ๋•Œ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ๋‹ค. ๊ฐ ๊ฐ์ฒด๋งˆ๋‹ค ๋ฉ”๋ชจ๋ฆฌ์™€ ๊ณต๊ฐ„์„ ์žก์•„๋จน๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์–‘์ด ๋‚ฎ์€ ์ปดํ“จํ„ฐ๋‚˜ ๋ชจ๋ฐ”์ผ ๊ธฐ๊ธฐ์—์„œ๋Š” ๋ฉ”๋ชจ๋ฆฌ์™€ ๊ณต๊ฐ„์— ๋Œ€ํ•œ ์ œ์•ฝ์„ ํ”ผํ•  ์ˆ˜ ์—†๋Š”๋ฐ ๋งŒ์•ฝ ๋‚ด๊ฐ€ ๋งŒ๋“œ๋Š” ํ”„๋กœ๊ทธ๋žจ์ด ์—„์ฒญ ๋งŽ์€ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค๋ฉด ์ด ํŒจํ„ด์„ ๊ณต๋ถ€ํ•ด์„œ ์ ์šฉํ•ด๋ณด๊ธฐ ๋ฐ”๋ž€๋‹ค. ํ”Œ๋ผ์ด์›จ์ดํŠธ ํŒจํ„ด์€ ๊ฐ์ฒด๋ฅผ ๊ณต์œ ํ•จ์œผ๋กœ์จ ๋ฉ”๋ชจ๋ฆฌ ๋ถ€ํ•˜๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. 


์œ ์šฉ์„ฑ ( Applicability ) :

The Flyweight pattern's effectiveness depends heavily on how and where it's used.

ํ”Œ๋ผ์ด์›จ์ดํŠธ ํŒจํ„ด์˜ ํšจ๊ณผ๋Š” ์–ด๋–ป๊ฒŒ ์–ด๋””์„œ ์‚ฌ์šฉ๋˜๋Š๋ƒ์— ๋”ฐ๋ผ ์‹ฌํ•˜๊ฒŒ ์ขŒ์ง€์šฐ์ง€ ๋œ๋‹ค.


Apply the Flyweight pattern when all of the following are true:

์•„๋ž˜ ๋‚ด์šฉ๊ณผ ๋ชจ๋‘ ๋งž์•„ ๋–จ์–ด์ง€๋Š” ์ƒํ™ฉ์—์„œ๋งŒ ์ด ํŒจํ„ด์„ ์ ์šฉํ•˜๋ฉด ๋œ๋‹ค.


ยท An application uses a large number of objects.

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์ •๋ง ๋งŽ์€ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ
ยท Storage costs are high because of the sheer quantity of objects.

์ €์žฅ๋น„์šฉ์ด ๋†’์„ ๋•Œ( ๊ฐ์ฒด ๊ฐœ์ˆ˜๊ฐ€ ๋งŽ์•„์„œ )
ยท Most object state can be made extrinsic.

๋Œ€๋ถ€๋ถ„์˜ ๊ฐ์ฒด์˜ ์ƒํƒœ๊ฐ€ ๋ถ€๋Œ€์ ์ธ ๊ฒƒ์ผ ๋•Œ
ยท Many groups of objects may be replaced by relatively few shared objects once extrinsic state is removed.

๋ถ€๋Œ€์ ์ธ ์ƒํƒœ๊ฐ€ ์ œ๊ฑฐ๋์„ ๋•Œ์—๋Š” ์ ์€ ์ˆ˜์˜ ๊ณต์œ  ๊ฐ์ฒด๋กœ ๋งŽ์€ ์ˆ˜์˜ ๊ฐ์ฒด๋ฅผ ๋Œ€์ฒดํ•  ์ˆ˜ ์žˆ์„ ๋•Œ
ยท The application doesn't depend on object identity. Since flyweight objects may be shared, identity tests will return true for conceptually distinct objects.

์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๊ฐ์ฒด์˜ identity์— ์˜์กด์ ์ด์ง€ ์•Š์„ ๋•Œ 


๋“ฑ์žฅ ์ธ๋ฌผ ( Participants ) :

ยท Flyweight
o declares an interface through which flyweights can receive and act
on extrinsic state.
ยท ConcreteFlyweight (Character)
o implements the Flyweight interface and adds storage for intrinsic state, if any. A ConcreteFlyweight object must be sharable. Any state it stores must be intrinsic; that is, it must be independent of the ConcreteFlyweight object's context.
ยท UnsharedConcreteFlyweight (Row, Column)
o not all Flyweight subclasses need to be shared. The Flyweight interface enables sharing; it doesn't enforce it. It's common for
UnsharedConcreteFlyweight objects to have ConcreteFlyweight objects as children at some level in the flyweight object structure
(as the Row and Column classes have).
ยท FlyweightFactory
o creates and manages flyweight objects.
o ensures that flyweights are shared properly. When a client requests a flyweight, the FlyweightFactory object supplies an existing
instance or creates one, if none exists.  

ยท Client
o maintains a reference to flyweight(s).
o computes or stores the extrinsic state of flyweight(s).


์›๋ฆฌ ( Collaborations ) :

ยท State that a flyweight needs to function must be characterized as either intrinsic or extrinsic. Intrinsic state is stored in the ConcreteFlyweight object; extrinsic state is stored or computed by Client objects. Clients pass this state to the flyweight when they invoke its operations.
ยท Clients should not instantiate ConcreteFlyweights directly. Clients must obtain ConcreteFlyweight objects exclusively from the FlyweightFactory object to ensure they are shared properly.


ํŒจํ„ด ์‚ฌ์šฉ์˜ ์žฅ๋‹จ์  ( Consequences ): 

 
Flyweights may introduce run-time costs associated with transferring, finding, and/or computing extrinsic state, especially if it was formerly stored as intrinsic state. However, such costs are offset by space savings, which increase as more
flyweights are shared.


Storage savings are a function of several factors:


ยท the reduction in the total number of instances that comes from sharing
ยท the amount of intrinsic state per object
ยท whether extrinsic state is computed or stored.


The more flyweights are shared, the greater the storage savings. The savings increase with the amount of shared state. The greatest savings occur when the objects use substantial quantities of both intrinsic and extrinsic state, and the extrinsic state can be computed rather than stored. Then you save on storage in two ways: Sharing reduces the cost of intrinsic state, and you trade extrinsic state for computation time.
The Flyweight pattern is often combined with the Composite (183) pattern to represent a hierarchical structure as a graph with shared leaf nodes. A consequence of sharing is that flyweight leaf nodes cannot store a pointer to their parent. Rather, the parent pointer is passed to the flyweight as part of its extrinsic state. This has a major impact on how the objects in the hierarchy  communicate with each other. 

 

๊ด€๋ จ ํŒจํ„ด๋“ค : 

The Flyweight pattern is often combined with the Composite pattern to implement a logically hierarchical structure in terms of a directed-acyclic graph with shared leaf nodes.

It's often best to implement State and Strategy objects as flyweights. 


์ถ”๊ฐ€ ์ •๋ณด :   

  • Whereas Flyweight shows how to make lots of little objects, Facade shows how to make a single object represent an entire subsystem.
  • Flyweight is often combined with Composite to implement shared leaf nodes.
  • Terminal symbols within Interpreter's abstract syntax tree can be shared with Flyweight.
  • Flyweight explains when and how State objects can be shared.
  • Flyweight pattern introduces complexity and if number of shared objects are huge then there is a trade of between memory and time, so we need to use it judiciously based on our requirements.
  • Flyweight pattern implementation is not useful when the number of intrinsic properties of Object is huge, making implementation of Factory class complex.

 

 

 

์ถœ์ฒ˜ :  http://sourcemaking.com/design_patterns/flyweight

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

http://www.journaldev.com/1562/flyweight-pattern-in-java-example-tutorial

 


 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.

์ด ํŒจํ„ด๋“ค์€ ๊ฐ์ฒด๋“ค ์‚ฌ์ด์˜ ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜์— ๊ด€์‹ฌ์„ ๊ฐ€์ง„๋‹ค.

 

์˜ค๋Š˜ ์‚ดํŽด๋ณผ  Singleton ํŒจํ„ด์€ Creational ํŒจํ„ด์— ์†ํ•œ๋‹ค.  

 

Singleton Pattern Structure


 

ํŒจํ„ด์˜ ๋ชฉ์  ( Intent ) : 

Ensure a class only has one instance, and provide a global point of access to it.

ํ”„๋กœ๊ทธ๋žจ์ƒ์—์„œ ๋‹จ ํ•˜๋‚˜์˜ ์ธ์Šคํ„ด์Šค๋งŒ์„ ์š”๊ตฌํ•˜๋Š” ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค ํ•„์š”๊ฐ€ ์žˆ์–ด์„œ ๋‚˜์˜จ ํŒจํ„ด์ด๋‹ค. globalํ•˜๊ฒŒ access๊ฐ€๋Šฅํ•œ ๋‹จ ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ์ด ์ด ํŒจํ„ด์˜ ๋ชฉ์ ์ด๋‹ค. 

 

ํŒจํ„ด์ด ๋‚˜์˜ค๊ฒŒ ๋œ ๋™๊ธฐ ( Motivation ) :

Application needs one, and only one, instance of an object. Additionally, lazy initialization and global access are necessary.

๋ชฉ์ ์—์„œ ๋งํ•œ ๋ฐ”์™€ ๊ฐ™์ด ๋‹จ ํ•˜๋‚˜์˜ ์œ ์ผํ•œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์ด๋ฅผ ์‚ฌ์šฉํ•  ๋ชฉ์ ์œผ๋กœ ๋‚˜์˜ค๊ฒŒ ๋œ ํŒจํ„ด์ด๋‹ค. ํ•œ๋ฒˆ ์ƒ์„ฑํ•˜๋ฉด ๊ทธ ์ดํ›„์—๋Š” ์ƒ์„ฑ๋œ ๊ฐ์ฒด๋ฅผ ์ด์šฉ๋งŒ ํ•  ๋ฟ์ด๋‹ค. 


์œ ์šฉ์„ฑ ( Applicability ) :

Use the Singleton pattern when
ยท there must be exactly one instance of a class, and it must be accessible to clients from a well-known access point.
ยท when the sole instance should be extensible by subclassing, and clients should be able to use an extended instance without modifying their code.

 

๋“ฑ์žฅ ์ธ๋ฌผ ( Participants ) :

ยท Singleton
o defines an Instance operation that lets clients access its unique instance. Instance is a class operation (that is, a class method in Smalltalk and a static member function in C++).
o may be responsible for creating its own unique instance.


์›๋ฆฌ ( Collaborations ) :

ยท Clients access a Singleton instance solely through Singleton's Instance operation.

ํด๋ผ์ด์–ธํŠธ๋“ค์€ ์ด ์‹ฑ๊ธ€ํ„ด๊ฐ์ฒด์—์„œ ์ œ๊ณตํ•˜๋Š”  getter๋ฉ”์†Œ๋“œ์— ์˜ํ•ด ์˜ค์ง ํ˜ผ์ž๋งŒ ์ ‘๊ทผํ•œ๋‹ค.


ํŒจํ„ด ์‚ฌ์šฉ์˜ ์žฅ๋‹จ์  ( Consequences ): 

The Singleton pattern has several benefits:
1. Controlled access to sole instance. Because the Singleton class encapsulates its sole instance, it can have strict control over how and when clients access it.
2. Reduced name space. The Singleton pattern is an improvement over global variables. It avoids polluting the name space with global variables that store sole instances.
3. Permits refinement of operations and representation. The Singleton class may be subclassed, and it's easy to configure an application with an instance of this extended class. You can configure the application with an instance of the class you need at run-time.
4. Permits a variable number of instances. The pattern makes it easy to change your mind and allow more than one instance of the Singleton class. Moreover, you can use the same approach to control the number of instances that the application uses. Only the operation that grants access to the Singleton instance needs to change.
5. More flexible than class operations. Another way to package a singleton's functionality is to use class operations (that is, static member functions in C++ or class methods in Smalltalk). But both of these language techniques make it hard to change a design to allow more than one instance of a class. Moreover, static member functions in C++ are never virtual, so subclasses can't override them polymorphically.

 

์†Œ์Šค ์˜ˆ์ œ : 


1. ์ผ๋ฐ˜์ ์ธ ๊ฒฝ์šฐ ( synchronizingํ•  ํ•„์š”๊ฐ€ ์—†๋Š” ์‹ฑ๊ธ€ํ„ด ๊ฐ์ฒด์˜ ๊ฒฝ์šฐ, ์‹ฑ๊ธ€์“ฐ๋ ˆ๋“œ(single thread) )

 

// ์‹ฑ๊ธ€ํ„ด๊ฐ์ฒด๊ฐ€ ํ•„์š”ํ•  ๋•Œ๋Š” ์ธ์Šคํ„ด์Šค๋ฅผ ์ง์ ‘ ๋งŒ๋“œ๋Š”๊ฒŒ ์•„๋‹ˆ๊ณ  ์ธ์Šคํ„ด์Šค๋ฅผ ๋‹ฌ๋ผ๊ณ  ์š”์ฒญ์„ ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.
public class Singleton {
  private static Singleton uniqueInstance;
 
  private Singleton() {}  // <---  ์ƒ์„ฑ์ž๋Š” private -- ์™ธ๋ถ€์—์„œ new ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์—†๋‹ค...
 
  public static Singleton getInstance() {  // ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” static ๋ฉ”์†Œ๋“œ ํ•˜๋‚˜
    if ( uniqueInstance == null ) {        // ์ด ๋ถ€๋ถ„์€ ๊ฐ์ฒด๋ฅผ ์ฒ˜์Œ ์ƒ์„ฑํ•  ๋•Œ๋งŒ ํ•„์š”ํ•˜๋‹ค~~
      uniqueInstance = new Singleton();
    }
    return uniqueInstance;
  }
}

2. ์—ฌ๋Ÿฌ๋ช…์ด ๋™์‹œ์ ‘๊ทผํ•  ์ˆ˜๋„ ์žˆ๋Š”
์‹ฑ๊ธ€ํ„ด ๊ฐ์ฒด์˜ ๊ฒฝ์šฐ ( ๋ฉ€ํ‹ฐ์“ฐ๋ ˆ๋“œ, multi thread )

A. ์œ„ ์ฝ”๋“œ์˜ ๋ฌธ์ œ์  )
public class Singleton {
  private static Singleton uniqueInstance;
 
  private Singleton() {}
 
  public static Singleton getInstance() {  
    if ( uniqueInstance == null ) {          // A Thread๊ฐ€ ์ด ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•  ๋•Œ
      uniqueInstance = new Singleton();      // B Thread๊ฐ€ ๊ฐ์ฒด ์ƒ์„ฑ์„ ์™„๋ฃŒํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ 
    }                                        // ๋‘๊ฐœ์˜ ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋  ์ˆ˜ ์žˆ๋‹ค.
 
    return uniqueInstance;
  }
}

B.Method synchronizing ์œผ๋กœ ๋ฌธ์ œ ํ•ด๊ฒฐ ๊ฐ€๋Šฅ 

 

public class Singleton {
  private static Singleton uniqueInstance;
 
  private Singleton() {}

  // ๋ฉ”์†Œ๋“œ ์ž์ฒด์— synchronized ๋ฅผ ๊ฑฐ๋Š” ๋ฐฉ๋ฒ• 
  public static synchronized Singleton getInstance() {  
    if ( uniqueInstance == null ) {          
      uniqueInstance = new Singleton(); 
    }                                        
 
    return uniqueInstance;
  }
}

์ด ๋ฐฉ๋ฒ•์˜ ๋ฌธ์ œ์  )
  • ์ด ๋ฐฉ๋ฒ•์€ ์„ฑ๋Šฅ์— ์˜ํ–ฅ์„ ๋ผ์น  ์ˆ˜ ์žˆ๋‹ค.
    ( ๋ฉ”์†Œ๋“œ๋ฅผ ๋™๊ธฐํ™”ํ•˜๋ฉด ์„ฑ๋Šฅ์ด 100๋ฐฐ ์ •๋„ ์ €ํ•˜๋œ๋‹ค๊ณ  ์ฑ…์— ์ ํ˜€์žˆ์Šต๋‹ˆ๋‹ค. )
  • synchronized๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ๋Š” ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋˜๋Š” ์ฒ˜์Œ ๋ฟ์ด๊ณ  ๊ทธ ์ดํ›„์—๋Š” ์“ธ๋ฐ์—†์ด ์„ฑ๋Šฅ์„ ์ €ํ•˜์‹œํ‚ค๋Š” ์š”์ธ์ด๋‹ค.

C. Double-checking Locking

public class Singleton { private volatile static Singleton uniqueInstance; private Singleton() {} // ๋ถ€๋ถ„์ ์œผ๋กœ synchronized๋ฅผ ๊ฑธ์–ด ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋œ ์ดํ›„์—๋Š” synchronized ๊ตฌ๋ฌธ์„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š๋Š”๋‹ค. public static Singleton getInstance() { if ( uniqueInstance == null ) { synchronized( Singleton.class ) { if ( uniqueInstance == null ) { uniqueInstance = new Singleton(); } } } return uniqueInstance; } }

๊ด€๋ จ ํŒจํ„ด๋“ค : 

 Many patterns can be implemented using the Singleton pattern. See Abstract Factory, Builder, and Prototype.

 

์ถ”๊ฐ€ ์ •๋ณด :     

  • Abstract Factory, Builder, and Prototype can use Singleton in their implementation.
  • Facade objects are often Singletons because only one Facade object is required.
  • State objects are often Singletons.
  • The advantage of Singleton over global variables is that you are absolutely sure of the number of instances when you use Singleton, and, you can change your mind and manage any number of instances.
  • The Singleton design pattern is one of the most inappropriately used patterns. Singletons are intended to be used when a class must have exactly one instance, no more, no less. Designers frequently use Singletons in a misguided attempt to replace global variables. A Singleton is, for intents and purposes, a global variable. The Singleton does not do away with the global; it merely renames it.
    ์‹ฑ๊ธ€ํ„ด ํŒจํ„ด์€ ๊ฐ€์žฅ ๋ถ€์ ์ ˆํ•˜๊ฒŒ ์‚ฌ์šฉ๋˜๋Š” ํŒจํ„ด์ค‘ ํ•˜๋‚˜์ด๋‹ค. ์›๋ž˜ ์‹ฑ๊ธ€ํ„ด ํŒจํ„ด์˜ ๋ชฉ์ ์€ ๋”๋„๋ง๊ณ  ๋œ๋„๋ง๊ณ  ์˜ค๋กœ์ง€ ๋‹จ ํ•˜๋‚˜์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ–๊ธฐ ์œ„ํ•จ์ด์—ˆ์œผ๋‚˜ ์ผ๋ถ€ ๊ฐœ๋ฐœ์ž๋“ค์€ ๋‹จ์ˆœํžˆ ์ „์—ญ๋ณ€์ˆ˜๋ฅผ ๋Œ€์ฒดํ•˜๊ธฐ์œ„ํ•ด ์‚ฌ์šฉํ•  ๋•Œ๊ฐ€ ์žˆ๋‹ค.
  • When is Singleton unnecessary? Short answer: most of the time. Long answer: when it's simpler to pass an object resource as a reference to the objects that need it, rather than letting objects access the resource globally. The real problem with Singletons is that they give you such a good excuse not to think carefully about the appropriate visibility of an object. Finding the right balance of exposure and protection for an object is critical for maintaining flexibility.
  • Our group had a bad habit of using global data, so I did a study group on Singleton. The next thing I know Singletons appeared everywhere and none of the problems related to global data went away. The answer to the global data question is not, "Make it a Singleton." The answer is, "Why in the hell are you using global data?" Changing the name doesn't change the problem. In fact, it may make it worse because it gives you the opportunity to say, "Well I'm not doing that, I'm doing this" โ€“ even though this and that are the same thing.

 

 

 

์ถœ์ฒ˜ :  http://sourcemaking.com/design_patterns/singleton

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

http://www.javajigi.net/display/SWD/ch05_singletonpattern

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.

์ด ํŒจํ„ด๋“ค์€ ๊ฐ์ฒด๋“ค ์‚ฌ์ด์˜ ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜์— ๊ด€์‹ฌ์„ ๊ฐ€์ง„๋‹ค.

 

์˜ค๋Š˜ ์‚ดํŽด๋ณผ  Prototype ํŒจํ„ด์€ Creational ํŒจํ„ด์— ์†ํ•œ๋‹ค.  

 

Prototype Pattern Structure



ํŒจํ„ด์˜ ๋ชฉ์  ( Intent ) : 

- Specify the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype. 

ํ•˜๋‚˜์˜ ํ”„๋กœํ† ํƒ€์ž… ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค๊ณ  ํ•„์š”ํ• ๋•Œ๋งˆ๋‹ค ํ”„๋กœํ† ํƒ€์ž… ์ธ์Šคํ„ด์Šค๋ฅผ ๋ณต์‚ฌํ•ด์„œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•จ 

- Co-opt one instance of a class for use as a breeder of all future instances. 

- The new operator considered harmful.

new ํ‚ค์›Œ๋“œ๋ฅผ ์ด์šฉํ•˜๋Š” ๊ฒƒ์ด ์•ˆ์ข‹์€ ์ƒํ™ฉ์ผ ๋•Œ ํ”„๋กœํ† ํƒ€์ž… ํŒจํ„ด์„ ์ด์šฉํ•˜์ž. 

 

ํŒจํ„ด์ด ๋‚˜์˜ค๊ฒŒ ๋œ ๋™๊ธฐ ( Motivation ) :

 

๊ฐ์ฒด ์ƒ์„ฑ ๋น„์šฉ์ด ๋น„์‹ผ๊ฒฝ์šฐ ํ”„๋กœํ† ํƒ€์ž… ์›ํ˜•์„ ๋งŒ๋“ค๊ณ  ํด๋กœ๋‹ ๊ธฐ๋ฒ•์„ ์ด์šฉํ•ด์„œ ๊ฐ์ฒด๋ฅผ ์‰ฝ๊ฒŒ ์ƒ์„ฑํ•˜๊ณ ์ž ํ•˜๊ธฐ ์œ„ํ•จ.


์œ ์šฉ์„ฑ ( Applicability ) :

Use the Prototype pattern when a system should be independent of how its products are created, composed, and represented; and
ยท when the classes to instantiate are specified at run-time, for example, by dynamic loading; or

ํด๋ž˜์Šค์˜ ๋™์ ๋กœ๋”ฉ์ด ํ•„์š”ํ•  ๋•Œ
ยท to avoid building a class hierarchy of factories that parallels the class hierarchy of products; or

์ œํ’ˆ์˜ ํด๋ž˜์Šค ๊ณ„์ธต๊ณผ ๋™์ผํ•œ ํŒฉํ† ๋ฆฌ ํด๋ž˜์Šค ๊ณ„์ธต์„ ๋งŒ๋“ค๊ณ  ์‹ถ์ง€ ์•Š์„ ๋•Œ
ยท when instances of a class can have one of only a few different combinations of state. It may be more convenient to install a corresponding number of prototypes and clone them rather than instantiating the class manually, each time with the appropriate state.

 

๋“ฑ์žฅ ์ธ๋ฌผ ( Participants ) :

ยท Prototype
o declares an interface for cloning itself.
ยท ConcretePrototype
o implements an operation for cloning itself.
ยท Client
o creates a new object by asking a prototype to clone itself. 


์›๋ฆฌ ( Collaborations ) :

ยท A client asks a prototype to clone itself.


ํŒจํ„ด ์‚ฌ์šฉ์˜ ์žฅ๋‹จ์  ( Consequences ): 

Prototype has many of the same consequences that Abstract Factory and Builder have: It hides the concrete product classes from the client, thereby reducing the number of names clients know about. Moreover, these patterns let a client work with application-specific classes without modification.


Additional benefits of the Prototype pattern are listed below.


1. Adding and removing products at run-time. Prototypes let you incorporate a new concrete product class into a system simply by registering a prototypical instance with the client. That's a bit more flexible than other creational patterns, because a client can install and remove prototypes at run-time.


2. Specifying new objects by varying values. Highly dynamic systems let you define new behavior through object compositionโ€”by specifying values for an object's variables, for exampleโ€”and not by defining new classes. You effectively define new kinds of objects by instantiating existing classes and registering the instances as prototypes of client objects. A client can exhibit new behavior by delegating responsibility to the prototype. This kind of design lets users define new "classes" without programming. In fact, cloning a prototype is similar to instantiating a class. The Prototype pattern can greatly reduce the number of classes a system needs. In our music editor, one GraphicTool class can create a limitless variety of music objects.


3. Specifying new objects by varying structure. Many applications build objects from parts and subparts. Editors for circuit design, for example, build circuits out of subcircuits.1 For convenience, such applications often let you instantiate complex, user-defined structures, say, to use a specific subcircuit again and again. The Prototype pattern supports this as well. We simply add this subcircuit as a prototype to the palette of available circuit elements. As long as the composite circuit object implements Clone as a deep copy, circuits with different structures can be prototypes.  

 

4. Reduced subclassing. Factory Method often produces a hierarchy of Creator classes that parallels the product class hierarchy. The Prototype pattern lets you clone a prototype instead of asking a factory method to make a new object. Hence you don't need a Creator class hierarchy at all. This benefit applies primarily to languages like C++ that don't treat classes as first-class objects. Languages that do, like Smalltalk and Objective C, derive less benefit, since you can always use a class object as a creator. Class objects already act like prototypes in these languages.


5. Configuring an application with classes dynamically. Some run-time environments let you load classes into an application dynamically. The Prototype pattern is the key to exploiting such facilities in a language like C++. An application that wants to create instances of a dynamically loaded class won't be able to reference its constructor statically. Instead, the run-time environment creates an instance of each class automatically when it's loaded, and it registers the instance with a prototype manager (see the
Implementation section). Then the application can ask the prototype manager for instances of newly loaded classes, classes that weren't linked with the program originally. The ET++ application framework [WGM88] has a run-time system that uses this scheme.
The main liability of the Prototype pattern is that each subclass of Prototype must implement the Clone operation, which may be difficult. For example, adding Clone is difficult when the classes under consideration already exist. Implementing Clone can be difficult when their internals include objects that don't support copying or have circular references.

 

๊ด€๋ จ ํŒจํ„ด๋“ค : 

 Prototype and Abstract Factory are competing patterns in some ways, as we discuss at the end of this chapter. They can also be used together, however. An Abstract Factory might store a set of prototypes from which to clone and return product objects.
Designs that make heavy use of the Composite and Decorator patterns often can benefit from Prototype as well.

 

์ถ”๊ฐ€ ์ •๋ณด :     

  • Sometimes creational patterns are competitors: there are cases when either Prototype or Abstract Factory could be used properly. At other times they are complementory: Abstract Factory might store a set of Prototypes from which to clone and return product objects. Abstract Factory, Builder, and Prototype can use Singleton in their implementations.
  • Abstract Factory classes are often implemented with Factory Methods, but they can be implemented using Prototype.
  • Factory Method: creation through inheritance. Protoype: creation through delegation.
  • Often, designs start out using Factory Method (less complicated, more customizable, subclasses proliferate) and evolve toward Abstract Factory, Protoype, or Builder (more flexible, more complex) as the designer discovers where more flexibility is needed.
  • Prototype doesn't require subclassing, but it does require an "initialize" operation. Factory Method requires subclassing, but doesn't require Initialize.
  • Designs that make heavy use of the Composite and Decorator patterns often can benefit from Prototype as well.
  • Prototype co-opts one instance of a class for use as a breeder of all future instances.
  • Prototypes are useful when object initialization is expensive, and you anticipate few variations on the initialization parameters. In this context, Prototype can avoid expensive "creation from scratch", and support cheap cloning of a pre-initialized prototype.
  • Prototype is unique among the other creational patterns in that it doesn't require a class โ€“ only an object. Object-oriented languages like Self and Omega that do away with classes completely rely on prototypes for creating new objects.

 

 

์ถœ์ฒ˜ :  http://sourcemaking.com/design_patterns/prototype

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

 


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.

์ด ํŒจํ„ด๋“ค์€ ๊ฐ์ฒด๋“ค ์‚ฌ์ด์˜ ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜์— ๊ด€์‹ฌ์„ ๊ฐ€์ง„๋‹ค.

 

์˜ค๋Š˜ ์‚ดํŽด๋ณผ  Factory Method ํŒจํ„ด์€ Creational ํŒจํ„ด์— ์†ํ•œ๋‹ค.  

 

Factory Method Pattern Structure


ํŒจํ„ด์˜ ๋ชฉ์  ( Intent ) : 

 Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.

ํŒฉํ† ๋ฆฌ ๋ฉ”์†Œ๋“œ ํŒจํ„ด์€ ํ•˜๋‚˜์˜ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ •์˜ํ•˜๋Š”๋ฐ ์ด๋•Œ ์–ด๋–ค ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•  ๊ฒƒ์ธ์ง€์— ๋Œ€ํ•œ ๊ฒฐ์ •๊ถŒ์€ ์„œ๋ธŒํด๋ž˜์Šค์—๊ฒŒ ์œ„์ž„ํ•œ๋‹ค. 

 

ํŒจํ„ด์ด ๋‚˜์˜ค๊ฒŒ ๋œ ๋™๊ธฐ ( Motivation ) :


ํ”„ ๋ ˆ์ž„์›Œํฌ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์ถ”์ƒํด๋ž˜์Šค๋กœ ๊ฐ์ฒด ์‚ฌ์ด์˜ ๊ด€๊ณ„๋ฅผ ์ •์˜ํ•˜๋Š”๋ฐ, ์ข…์ข… ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด์•ผ ํ•  ๋•Œ๋„ ์žˆ๋‹ค. ์•„๋ž˜ ๋‹ค์ด์–ด๊ทธ๋žจ์€ ๋‹ค์–‘ํ•œ ์ข…๋ฅ˜์˜ ๋ฌธ์„œ๋ฅผ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์ค„ ์ˆ˜ ์žˆ๋Š” ํ”„๋ ˆ์ž„์›Œํฌ์˜ ํด๋ž˜์Šค ๋‹ค์ด์–ด๊ทธ๋žจ์ด๋‹ค. ์•„๋ž˜ ๋‹ค์ด์–ด๊ทธ๋žจ์—์„œ ๊ด€๊ณ„๋ฅผ ๋งบ๊ณ  ์žˆ๋Š” ์ถ”์ƒํด๋ž˜์Šค๋“ค์€ Document์™€ Application์ด๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ๊ทธ๋ฆผ๊ทธ๋ฆฌ๊ธฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค๋ ค๋ฉด ๋‘ ์ถ”์ƒํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›์•„ DrawingApplication๊ณผ DrawingDocument ํด๋ž˜์Šค๋ฅผ ์ •์˜ํ•ด์•ผํ•˜๊ณ , Applicationํด๋ž˜์Šค๋Š” ํ•„์š”์—๋”ฐ๋ผ Document ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑ ํ˜น์€ ์—ด๊ธฐ๊ฐ€ ๊ฐ€๋Šฅํ•ด์•ผ ํ•œ๋‹ค. 

์ž, ๊ทธ๋Ÿฐ๋ฐ ๋ฌธ์ œ๋Š” ํŠน์ • ๋ฌธ์„œ๋Š” ํŠน์ • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์˜์กด์ ์ด๋ผ๋Š” ์ ์ด๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, docx๋Š” ์›Œ๋“œ์—์„œ ์ƒ์„ฑํ•˜๋Š” ๋ฌธ์„œ์ด์ง€ ํ•œ๊ธ€์—์„œ ์ƒ์„ฑํ•˜๋Š” ๋ฌธ์„œ๊ฐ€ ์•„๋‹Œ ๊ฒƒ๊ณผ ๊ฐ™์€ ํ˜„์ƒ์ด๋ผ๊ณ  ๋ณด๋ฉด ๋œ๋‹ค. ๋”ฐ๋ผ์„œ Application์˜ CreateDocument()๋ฅผ ์ถ”์ƒ๋ฉ”์†Œ๋“œ๋กœ ์ •์˜ํ•˜๊ณ  ์ด๋ฅผ ์„œ๋ธŒํด๋ž˜์Šค์—์„œ ๊ตฌํ˜„ํ•˜๋„๋ก ํ•˜์—ฌ ๊ฐ๊ฐ์˜ Application๋งˆ๋‹ค ๊ฐ๊ฐ์˜ Document๋ฅผ ์ƒ์„ฑํ•˜๋„๋ก ํ•œ ๊ฒƒ์ด๋‹ค. ์ด๋•Œ CreateDocument()๋ฅผ ํŒฉํ† ๋ฆฌ ๋ฉ”์†Œ๋“œ๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค. 

 

 

์œ ์šฉ์„ฑ ( Applicability ) :

 Use the Factory Method pattern when


ยท a class can't anticipate the class of objects it must create.
ยท a class wants its subclasses to specify the objects it creates.
ยท classes delegate responsibility to one of several helper subclasses, and you want to localize the knowledge of which helper subclass is the delegate.


๋“ฑ์žฅ ์ธ๋ฌผ ( Participants ) :

ยท Product (Document)
o defines the interface of objects the factory method creates.
ยท ConcreteProduct (MyDocument)
o implements the Product interface.
ยท Creator (Application)
o declares the factory method, which returns an object of type Product. Creator may also define a default implementation of the factory method that returns a default ConcreteProduct object.
o may call the factory method to create a Product object.
ยท ConcreteCreator (MyApplication)
o overrides the factory method to return an instance of a ConcreteProduct.


์›๋ฆฌ ( Collaborations ) :

ยท Creator relies on its subclasses to define the factory method so that it returns an instance of the appropriate ConcreteProduct.


ํŒจํ„ด ์‚ฌ์šฉ์˜ ์žฅ๋‹จ์  ( Consequences ): 

 Factory methods eliminate the need to bind application-specific classes into your code. The code only deals with the Product interface; therefore it can work with any user-defined ConcreteProduct classes. A potential disadvantage of factory methods is that clients might have to subclass the Creator class just to create a particular ConcreteProduct object. Subclassing is fine when the client has to subclass the Creator class anyway, but otherwise the client now must deal with another point of evolution. 

 

Here are two additional consequences of the Factory Method pattern:


1. Provides hooks for subclasses. Creating objects inside a class with a factory method is always more flexible than creating an object directly. Factory Method gives subclasses a hook for providing an extended version of an object.
In the Document example, the Document class could define a factory method called CreateFileDialog that creates a default file dialog object for opening an existing document. A Document subclass can define an application-specific file dialog by overriding this factory method. In this  case the factory method is not abstract but provides a reasonable default implementation.


2. Connects parallel class hierarchies. In the examples we've considered so far, the factory method is only called by Creators. But this doesn't have to be the case; clients can find factory methods useful, especially in the case of parallel class hierarchies.
Parallel class hierarchies result when a class delegates some of its responsibilities to a separate class. Consider graphical figures that can be manipulated interactively; that is, they can be stretched, moved, or rotated using the mouse. Implementing such interactions isn't always easy.
It often requires storing and updating information that records the state of the manipulation at a given time. This state is needed only during manipulation; therefore it needn't be kept in the figure object. Moreover, different figures behave differently when the user manipulates them. For example, stretching a line figure might have the effect of moving an endpoint, whereas stretching a text figure may change its line spacing. With these constraints, it's better to use a separate Manipulator object that implements the interaction and keeps track of any manipulation-specific state that's needed. Different figures will use different Manipulator subclasses to handle particular interactions. The resulting Manipulator class hierarchy parallels (at least partially) the Figure class hierarchy:


The Figure class provides a CreateManipulator factory method that lets clients create a Figure's corresponding Manipulator. Figure subclasses override this method to return an instance of the Manipulator subclass that's right for them. Alternatively, the Figure class may implement CreateManipulator to return a default Manipulator instance, and Figure subclasses may simply inherit that default. The Figure classes that do so need no corresponding Manipulator subclassโ€”hence the hierarchies are only partially parallel.
Notice how the factory method defines the connection between the two class hierarchies. It localizes knowledge of which classes belong together.

 

๊ด€๋ จ ํŒจํ„ด๋“ค : 

 Abstract Factory is often implemented with factory methods. The Motivation example in the Abstract Factory pattern illustrates Factory Method as well.
Factory methods are usually called within Template Methods. In the document example above, NewDocument is a template method.
Prototypes don't require subclassing Creator. However, they often require an Initialize operation on the Product class. Creator uses Initialize to initialize the object. Factory Method doesn't require such an operation.

 

์ถ”๊ฐ€ ์ •๋ณด :     

 
  • Abstract Factory classes are often implemented with Factory Methods, but they can be implemented using Prototype.
  • Factory Methods are usually called within Template Methods.
  • Factory Method: creation through inheritance. Prototype: creation through delegation.
  • Often, designs start out using Factory Method (less complicated, more customizable, subclasses proliferate) and evolve toward Abstract Factory, Prototype, or Builder (more flexible, more complex) as the designer discovers where more flexibility is needed.
  • Prototype doesn't require subclassing, but it does require an Initialize operation. Factory Method requires subclassing, but doesn't require Initialize.
  • The advantage of a Factory Method is that it can return the same instance multiple times, or can return a subclass rather than an object of that exact type.
  • Some Factory Method advocates recommend that as a matter of language design (or failing that, as a matter of style) absolutely all constructors should be private or protected. It's no one else's business whether a class manufactures a new object or recycles an old one.
  • The new operator considered harmful. There is a difference between requesting an object and creating one. The new operator always creates an object, and fails to encapsulate object creation. A Factory Method enforces that encapsulation, and allows an object to be requested without inextricable coupling to the act of creation.

 

์ถœ์ฒ˜ :  http://sourcemaking.com/design_patterns/factory_method

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


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.

์ด ํŒจํ„ด๋“ค์€ ๊ฐ์ฒด๋“ค ์‚ฌ์ด์˜ ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜์— ๊ด€์‹ฌ์„ ๊ฐ€์ง„๋‹ค.

 

์˜ค๋Š˜ ์‚ดํŽด๋ณผ  Abstract Factory ํŒจํ„ด์€ Creational ํŒจํ„ด์— ์†ํ•œ๋‹ค.  

 

Abstract Factory Pattern Structure


ํŒจํ„ด์˜ ๋ชฉ์  ( Intent ) : 

Provide an interface for creating families of related or dependent objects without specifying their concrete classes.

์ถ”์ƒ ํŒฉํ† ๋ฆฌ ํŒจํ„ด์€ ๊ตฌ์ƒํด๋ž˜์Šค๋ฅผ ๋ช…์‹œํ•˜์ง€ ์•Š์•„๋„ ์—ฐ๊ด€์žˆ๊ฑฐ๋‚˜ ์˜์กด์ ์ธ ๊ฐ์ฒด์˜ ๊ทธ๋ฃน์„ ์ƒ์„ฑํ•˜๊ธฐ์œ„ํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•˜๋Š” ํŒจํ„ด์ด๋‹ค.

์ฐธ๊ณ ๋กœ Factory๋Š” ์‹ฑ๊ธ€ํ„ด ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ด๋‹ค. ( ๋™์ผํ•œ ์ œํ’ˆ์„ ์ƒ์‚ฐํ•˜๋Š” ๋‘๊ฐœ์˜ ๋‹ค๋ฅธ ๊ณต์žฅ์„ ํ•˜๋‚˜์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๊ฐ€์ง€๊ณ  ์žˆ์„ ํ•„์š”๋Š” ์—†๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ) 

 

ํŒจํ„ด์ด ๋‚˜์˜ค๊ฒŒ ๋œ ๋™๊ธฐ ( Motivation ) :



 GOF์˜ ๋””์ž์ธ ํŒจํ„ด์—์„œ ์˜ˆ๋กœ ๋“  ๋‚ด์šฉ์„ ์ข€ ๊พธ๋ฉฐ์„œ ์–˜๊ธฐํ•ด๋ณด๊ฒ ๋‹ค.  

์ž, ์šฐ๋ฆฌ ํšŒ์‚ฌ๋Š” ์—ฌ๋Ÿฌ๊ฐœ์˜ ์œ„์ ฏ์„ ์ œ๊ณตํ•˜๋Š”๋ฐ ์œ„์ ฏ๋งˆ๋‹ค Look and Feel ( ์ดํ•˜ LNF )์ด ๋‹ค๋ฅด๋‹ค. ์ง€๊ธˆ๊นŒ์ง€ Window์™€ ScrollBar๋ฅผ ๋‚ด๊ฐ€ ๋งŒ๋“ค์–ด ๋†จ๋Š”๋ฐ ์‹ ์ž…๊ฐœ๋ฐœ์ž๊ฐ€ ์ด๋ฅผ ์ด์šฉํ•ด์„œ ์œ„์ ฏ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ฃผ๊ณ  ์‹ถ๋‹ค. ๊ทธ๋ž˜์„œ ๋‚˜๋Š” WidgetFactory๋ฅผ ๋งŒ๋“ค์–ด ์‹ ์ž…๊ฐœ๋ฐœ์ž๊ฐ€ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•  ๊ฒƒ์ด๋‹ค. ๋‚ด๊ฐ€ ๋งŒ๋“  Window์™€ ScrollBar์˜ ๊ตฌ์ƒ ํด๋ž˜์Šค๋ฅผ ๋ชฐ๋ผ๋„ WidgetFactory์—์„œ ์•Œ์•„์„œ ์ƒ์„ฑํ•ด ์ค„ ํ…Œ๋‹ˆ ์‹ ์ž…๊ฐœ๋ฐœ์ž๋Š” WidgetFactory ์‚ฌ์šฉ๋ฒ•๋งŒ ์•Œ๋ฉด ๋˜๊ฒ ์ง€. ์‹ ์ž…๊ฐœ๋ฐœ์ž๊ฐ€ PMWidget์„ ๋งŒ๋“ค๊ณ  ์‹ถ์œผ๋ฉด PMWidgetFactory๋ฅผ ์ด์šฉํ•˜๋ฉด๋˜๊ณ  MotifWidget์„ ๋งŒ๋“ค๊ณ  ์‹ถ์œผ๋ฉด MotifWidgetFactory๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋˜๋Š”๊ฑฐ๋‹ค. 


์œ ์šฉ์„ฑ ( Applicability ) :

Use the Abstract Factory pattern when


ยท a system should be independent of how its products are created, composed, and represented.
ยท a system should be configured with one of multiple families of products.  

ยท a family of related product objects is designed to be used together, and you need to enforce this constraint.
ยท you want to provide a class library of products, and you want to reveal just their interfaces, not their implementations.

 

๋“ฑ์žฅ ์ธ๋ฌผ ( Participants ) :

ยท AbstractFactory (WidgetFactory)
o declares an interface for operations that create abstract product objects.
ยท ConcreteFactory (MotifWidgetFactory, PMWidgetFactory)
o implements the operations to create concrete product objects.
ยท AbstractProduct (Window, ScrollBar)
o declares an interface for a type of product object.
ยท ConcreteProduct (MotifWindow, MotifScrollBar)
o defines a product object to be created by the corresponding concrete factory.
o implements the AbstractProduct interface.
ยท Client
o uses only interfaces declared by AbstractFactory and AbstractProduct classes.


์›๋ฆฌ ( Collaborations ) :

ยท Normally a single instance of a ConcreteFactory class is created at run-time.
This concrete factory creates product objects having a particular implementation. To create different product objects, clients should use a different concrete factory.
ยท AbstractFactory defers creation of product objects to its ConcreteFactory subclass.

 



ํŒจํ„ด ์‚ฌ์šฉ์˜ ์žฅ๋‹จ์  ( Consequences ): 

The Abstract Factory pattern has the following benefits and liabilities:


1. It isolates concrete classes. The Abstract Factory pattern helps you control the classes of objects that an application creates. Because a factory encapsulates the responsibility and the process of creating product objects, it isolates clients from implementation classes. Clients manipulate instances through their abstract interfaces. Product class names are isolated in the implementation of the concrete factory; they do not appear in client code.  

 

2. It makes exchanging product families easy. The class of a concrete factory appears only once in an applicationโ€”that is, where it's instantiated. This makes it easy to change the concrete factory an application uses. It can use different product configurations simply by changing the concrete factory. Because an abstract factory creates a complete family of products, the whole product family changes at once. In our user interface example, we can switch from Motif widgets to Presentation Manager widgets simply by switching the corresponding factory objects and recreating the interface.


3. It promotes consistency among products. When product objects in a family are designed to work together, it's important that an application use objects from only one family at a time. AbstractFactory makes this easy to enforce.


4. Supporting new kinds of products is difficult. Extending abstract factories to produce new kinds of Products isn't easy. That's because the AbstractFactory interface fixes the set of products that can be created. Supporting new kinds of products requires extending the factory interface, which involves changing the AbstractFactory class and all of its subclasses

์ƒˆ ๋กœ์šด ์ข…๋ฅ˜์˜ ์ œํ’ˆ์„ ์ƒ์‚ฐํ•˜๋Š” ๊ฒƒ์ด ํž˜๋“ค๋‹ค. ์ƒˆ๋กœ์šด ์ œํ’ˆ์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด AbstractFactory๊ฐ€ ๋ณ€๊ฒฝ์ด ๋˜๋ฉด ์ด๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ตฌ์ƒํด๋ž˜์Šค(concrete classes)๋“ค์ด ๋ชจ๋‘ ๋ณ€๊ฒฝ๋˜์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์ด๋Ÿฐ ๋ฌธ์ œ๋ฅผ ๋ณด์™„ํ•˜๊ธฐ ์œ„ํ•ด์„œ Prototype-based Factory ( ํ”„๋กœํ† ํƒ€์ž… ํŒจํ„ด์„ ์ด์šฉํ•œ Factory )๋ฅผ ์ด์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์žˆ๋‹ค.  

 

 

 

๊ด€๋ จ ํŒจํ„ด๋“ค : 

 AbstractFactory classes are often implemented with factory methods (Factory Method), but they can also be implemented using Prototype.
A concrete factory is often a singleton.

 

์ถ”๊ฐ€ ์ •๋ณด :     

  • Sometimes creational patterns are competitors: there are cases when either Prototype or Abstract Factory could be used profitably. At other times they are complementary: Abstract Factory might store a set of Prototypes from which to clone and return product objects, Builder can use one of the other patterns to implement which components get built. Abstract Factory, Builder, and Prototype can use Singleton in their implementation.
  • Abstract Factory, Builder, and Prototype define a factory object that's responsible for knowing and creating the class of product objects, and make it a parameter of the system. Abstract Factory has the factory object producing objects of several classes. Builder has the factory object building a complex product incrementally using a correspondingly complex protocol. Prototype has the factory object (aka prototype) building a product by copying a prototype object.
  • Abstract Factory classes are often implemented with Factory Methods, but they can also be implemented using Prototype.
  • Abstract Factory can be used as an alternative to Facade to hide platform-specific classes.
  • Builder focuses on constructing a complex object step by step. Abstract Factory emphasizes a family of product objects (either simple or complex). Builder returns the product as a final step, but as far as the Abstract Factory is concerned, the product gets returned immediately.
  • Often, designs start out using Factory Method (less complicated, more customizable, subclasses proliferate) and evolve toward Abstract Factory, Prototype, or Builder (more flexible, more complex) as the designer discovers where more flexibility is needed.

 

 

์ถœ์ฒ˜ :  http://sourcemaking.com/design_patterns/abstract_factory

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