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 )