GOF (22)

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 Mementoit 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 handledthe request can fall off the end of the chainwithout ever being handled. A request can also go unhandled when thechain is not configured properly.

 

관련 패턴들 : 

 

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

 

추가 정보 :   

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

 


 

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

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


 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 )