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.

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

 

오늘 살펴볼 State 패턴은 Behavioral 패턴에 속한다. 

 

State Pattern Structure

 

패턴의 목적 ( Intent ) : 

Allow an object to alter its behavior when its internal state changes.The object will appear to change its class.

State 패턴의 목적은 내부 상태의 변화에 따라 객체의 행위를 변경할 수 있도록 하기 위함이다.


 위 다이어그램을 예제로 들면 TCPConnection은 TCPState객체를 가지고 있는 클래스다. 그리고 이 TCPState객체는 상태를 나타내는 클래스로 크게 세가지 상태로 나뉘는데 ( Established, Listen, Closed ) 이 상태의 변화에 따라 TCPConnection에서 호출하는 open()메소드가 TCPEstablished객체의 open()이 될 수도 있고 TCPListen나  TCPClosed 객체의 open()이 될 수도 있다.  

 

유용성 ( Applicability ) :

· An object's behavior depends on its state, and it must change its behavior at run-time depending on that state.

객체의 행위가 상태에 따라 동적으로 변해야 할 때
· Operations have large, multipart conditional statements that depend on the object's state. This state is usually represented by one or more enumerated constants. Often, several operations will contain this same conditional structure. The State pattern puts each branch of the conditional in a
separate class. This lets you treat the object's state as an object in its own right that can vary independently from other objects.

어떤 작업이 객체의 상태에 의존하는 여러개의 큰 조건문을 가지고 있다고 해보자( 쉽게 말해 객체의 상태를 나타내는 상수값이 조건문의 조건절에 들어가 있다고 생각해보자 ). 일반적으로 상태라는 것은 최소 하나 이상의 상수값에 의해 표현이 될 수 있는데, 이를 상태패턴을 이용하여 클래스에 담아버리는 것이다. 즉, 객체의 상태값을 나타내는 객체를 만들어 버리는 것이다.

 

등장 인물 :
· Context (TCPConnection)
o defines the interface of interest to clients.
o maintains an instance of a Concrete State subclass that defines the current state.

· State (TCPState)
o defines an interface for encapsulating the behavior associated with a particular state of the Context. 

 

· ConcreteState subclasses (TCPEstablished, TCPListen, TCPClosed)
o each subclass implements a behavior associated with a state of the Context.

 

원리 ( Collaborations ) :

· Context delegates state-specific requests to the current ConcreteState object.

Context는 상태에 따른 메소드 호출을 ConcreteState객체에 위임한다.
· A context may pass itself as an argument to the State object handling the request. This lets the State object access the context if necessary.

상태객체가 Context를 필요로한다면 Context객체는 자신을 argument로 넘겨주어 상태객체에서 접근할 수 있도록 할 수 있다.
· Context is the primary interface for clients. Clients can configure a context with State objects. Once a context is configured, its clients don't have to deal with the State objects directly.

클라이언트는 상태객체를 이용해서 context를 설정할 수 있는데 한번 설정하면 그 다음부터는 상태객체에 직접적으로 접근할 필요가 없다.
· Either Context or the ConcreteState subclasses can decide which state succeeds another and under what circumstances.

Context 또는 ConcreteState의 하위 클래스들은 상태의 순서를 결정할 수 있다.


패턴 사용의 장단점 ( Consequences ):
1. It localizes state-specific behavior and partitions behavior for different states.The State pattern puts all behavior associated with a particular state into one object. Because all state-specific code lives in a State subclass, new states and transitions can be added easily by defining new subclasses.
An alternative is to use data values to define internal states and have Context operations check the data explicitly. But then we'd have look-alike conditional or case statements scattered throughout Context's implementation. Adding a new state could require changing several operations, which complicates maintenance.

The State pattern avoids this problem but might introduce another, because the pattern distributes behavior for different states across several State subclasses. This increases the number of classes and is less compact than a single class. But such distribution is actually good if there are many states, which would otherwise necessitate large conditional statements.
Like long procedures, large conditional statements are undesirable.They're monolithic and tend to make the code less explicit, which in turn makes them difficult to modify and extend. The State pattern offers a better way to structure state-specific code. The logic that determines the state transitions doesn't reside in monolithic if or switch statements but instead is partitioned between the State  subclasses. Encapsulating each state transition and action in a class elevates the idea of an execution state to full object status. That imposes structure on the code and makes its intent clearer. 

 

2. It makes state transitions explicit.When an object defines its current state solely in terms of internal data values, its state transitions have no explicit representation;they only show up as assignments to some variables. Introducing separate objects for different states makes the transitions more explicit. Also, State objects can protect the Context from inconsistent internal states, because state transitions are atomic from the Context's perspective—they happen by rebinding one variable (the Context's State object variable), not several. 

 

3. State objects can be shared.If State objects have no instance variables—that is, the state they represent is encoded entirely in their type—then contexts can sharea State object. When states are shared in this way, they are essentially flyweights (see Flyweight) with nointrinsic state, only behavior.


관련 패턴들 : 

The Flyweight pattern explains when and how State objects can be shared.

Flyweight 패턴은 언제 어떻게 상태 객체들이 공유되는지 설명해준다.

State objects are often Singletons.

상태 객체들은 대부분 싱글턴이다.



추가 정보 :

  • State objects are often Singletons.
  • Flyweight explains when and how State objects can be shared.
  • Interpreter can use State to define parsing contexts.
  • Strategy has 2 different implementations, the first is similar to State. The difference is in binding times (Strategy is a bind-once pattern, whereas State is more dynamic).
  • 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.
  • The implementation of the State pattern builds on the Strategy pattern. The difference between State and Strategy is in the intent. With Strategy, the choice of algorithm is fairly stable. With State, a change in the state of the "context" object causes it to select from its "palette" of Strategy objects.

 

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

         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.

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

 

오늘 살펴볼 Strategy패턴은 Behavioral 패턴에 속한다.  

 

우선 쉬운 이해를 위해서 아래 예제부터 보자.

Example

공항으로 가는 교통수단이 세가지가 있다.  버스, 자동차, 그리고 택시. 우리가 어떤 것을 타고갈 지는 가격, 이동하는데 걸리는 시간, 배차시간, 기름값 등등이 될 것이다. 이런것을 로직으로 구현한다고 생각해보자. 전략패턴을 공부하는 시간이니 전략이란 말을 써서 각각의 교통수단을 하나의 전략이라고 할 수 있을 것이다. 그리고 각 전략의 공통분모를 모아서 Strategy라는 클래스안에 넣었다. 이를 아래와 같이 그림으로 나타낼 수 있을 것이다. TransportationToAirport클래스는 당신의 두뇌라고 생각할 수 있을 것이다. 어떤 전략을 선택할 지 결정짓는 로직이 들어있는 곳이 될테니 말이다. 전략패턴을 간단하게 말하자면 이런 식의 패턴인거다. 좀 더 자세한 이론적인 얘기들은 아래에서 살펴보자. 

 

 

Strategy Pattern Structure

 

패턴의 목적 ( Intent ) : 

Define a family of algorithms, encapsulate each one, and make them interchangeable.
Strategy lets the algorithm vary independently from clients that use it.


전략 패턴은 교체가 가능한 알고리즘 그룹을 정의하고 각각의 알고리즘을 캡슐화하는 것이다.

다.



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

 

Suppose a Composition class is responsible for maintaining and updating the linebreaks of text displayed in a text viewer. Linebreaking strategies aren't implemented by the class Composition. Instead, they are implemented separately by subclasses of the abstract Compositor class. Compositor subclasses implement different strategies:

· SimpleCompositor implements a simple strategy that determines linebreaks one at a time.
·​ TeXCompositor implements the TeX algorithm for finding linebreaks. This strategy tries to optimize linebreaks globally, that is, one paragraph at a time.
· ArrayCompositor implements a strategy that selects breaks so that each row has a fixed number of items. It's useful for breaking a collection of icons into rows, for example. 

 

A Composition maintains a reference to a Compositor object. Whenever a Composition reformats its text, it forwards this responsibility to its Compositor object. The client of Composition specifies which Compositor should be used by installing the Compositor it desires into the Composition.

 

 

유용성 ( Applicability ) :

· many related classes differ only in their behavior. Strategies provide a way to configure a class with one of many behaviors.

연관된 많은 클래스들이 행하는 행위에 있어서만 다를 때


· you need different variants of an algorithm. For example, you might define algorithms  reflecting different space/time trade-offs.Strategies can be used when these variants are  implemented as a class hierarchy of algorithms.

클래스계층으로 이루어진 다양한 알고리즘이 필요할 때 전략패턴을 이용할 수 있다.


· an algorithm uses data that clients shouldn't know about. Use the Strategy pattern to avoid exposing complex, algorithm-specific data structures.

복잡하고 알고리즘에 특화된 데이타구조를 노출시키고 싶지 않으면 전략패턴을 이용할 수 있다.


· a class defines many behaviors, and these appear as multiple conditional statements in its operations. Instead of many conditionals, move related conditional branches into their own Strategy class.

한 클래스가 여러 행위를 정의하고 수많은 조건절에 의해 특정 행위를 해야할 때가 있다. 이럴 때는 많은 조건절대신에 연관있는 조건절들을 전략 클래스로 묶어버려라. 

 

 

등장 인물 ( Participants ) :
· Strategy (Compositor)
o declares an interface common to all supported algorithms. Context uses this interface to call the algorithm defined by a ConcreteStrategy.

지원가능한 모든 알고리즘의 공통 인터페이스를 정의한다. Context가 ConcreteStrategy에 의해 정의된 알고리즘을 호출하기 위해서 이 인터페이스를 이용한다. 

 

· ConcreteStrategy (SimpleCompositor, TeXCompositor,ArrayCompositor)  

o implements the algorithm using the Strategy interface.

Strategy 인터페이스를 이용해서 알고리즘을 구현한다.


· Context (Composition)
o is configured with a ConcreteStrategy object.

o maintains a reference to a Strategy object.  

Strategy객체로의 레퍼런스를 유지한다.
o may define an interface that lets Strategy access its data.  

Strategy가 Context의 데이타로 접근할 수 있도록 인터페이스를 정의할 수도 있다.

 

원리 ( Collaborations ) :

· Strategy and Context interact to implement the chosen algorithm. A context may pass all data required by the algorithm to the strategy when the algorithm is called. Alternatively, the context can pass itself as an argument to Strategy operations. That lets the strategy call back on the context as required.
· A context forwards requests from its clients to its strategy. Clients usually create and pass a ConcreteStrategy object to the context; thereafter, clients interact with the context exclusively. There is often a family of ConcreteStrategy classes for a client to choose from.


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

1. Families of related algorithms. Hierarchies of Strategy classes define a family of algorithms  or behaviors for contexts to reuse. Inheritance can help factor out common functionality of the algorithms.

전략패턴은 연관된 알고리즘그룹을 상속을 통해 클래스계층으로 만들어 이를 재사용할 수 있도록 한다.  

 

2. An alternative to subclassing. Inheritance offers another way to support a variety of algorithms or behaviors. You can subclass a Context class directly to give it different behaviors. But this hard-wires the behavior into Context. It mixes the algorithm implementation with Context's, making Context harder to understand, maintain, and extend. And you can't vary the algorithm dynamically. You wind up with many related classes whose only difference is the algorithm or behavior they employ. Encapsulating the algorithm in separate Strategy classes lets you vary the algorithm independently of its context, making it easier to switch, understand, and extend.


3. Strategies eliminate conditional statements. The Strategy pattern offers an alternative to conditional statements for selecting desired behavior. When different behaviors are lumped into one class, it's hard to avoid using conditional statements to select the right behavior. Encapsulating the behavior in separate Strategy classes eliminates these conditional statements.
Code containing many conditional statements often indicatesthe need to apply the Strategy pattern.


4. A choice of implementations. Strategies can provide different implementations of the  same behavior. The client can choose among strategies with different time and space trade-offs.


5. Clients must be aware of different Strategies.The pattern has a potential drawback in that a client must understand how Strategies differ before it can select the appropriate one. Clients might be exposed to implementation issues. Therefore you should use the Strategy pattern only when the variation in behavior is relevant to clients.


6. Communication overhead between Strategy and Context. The Strategy interface is shared by all ConcreteStrategy classes whether the algorithms they implement are trivial or complex. Hence it's likely that some ConcreteStrategies won't use all the information passed to them through this interface; simple ConcreteStrategies may use none of it! That means there will be times when the context creates and initializes parameters that never get used. If this is an issue, then you'll need tighter coupling between Strategy and Context.


7. Increased number of objects. Strategies increase the number of objects in an application. Sometimes you can reduce this overhead by implementing strategies as stateless objects that contexts can share. Any residual state is maintained by the context, which passes it in each request to the Strategy object. Shared strategies should not maintain state across invocations. The Flyweight pattern describes this approach in more detail.


관련 패턴들 : 

Flyweight

 

추가 정보 :   

  • Strategy is like Template Method except in its granularity.
    Strategy 패턴은 Template Method 패턴과 비슷하다. ( granularity를 제외하면 )
    ( granularity를 테크놀로지컬하게 뭐라고 해석해야할 지 모르겠네요.)

  • State is like Strategy except in its intent.
    State 패턴은 Strategy 패턴과 비슷하다. ( intent를 제외하면 )
  • Strategy lets you change the guts of an object. Decorator lets you change the skin.
    Strategy 패턴을 이용해서 객체내부를 변경할 수 있다면, Decorator 패턴은 객체껍데기를 변경할 수 있게 해준다.
  • 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.
    State, Strategy, Bridge 패턴들은 모두 비슷한 구조를 갖고 있지만, 패턴의 목적(intent)가 다르다. 즉, 서로 다른 문제를 해결하기 위해서 나온 패턴들이라는 얘기다.
  • Strategy has 2 different implementations, the first is similar to State. The difference is in binding times (Strategy is a bind-once pattern, whereas State is more dynamic).
    Strategy 패턴이 정적으로 한번 바인딩하는 반면 State 패턴은 동적으로 바인딩한다.
  • Strategy objects often make good Flyweights.
    Strategy 객체들은 보통 좋은 Filyweights를 만든다. ( Flyweight 패턴을 공부하면 무슨 말인지 이해가 될 듯 싶네요 )

 

 

 

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

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