1.1. Intent ¶
비슷한 문제들을 해결할 수 있는 알고리즘의 군들을 정의하고, 각각의 알고리즘을 캡슐화하고, 그 알고리즘들을 교환할 수 있도록 한다. Strategy는 알고리즘들로 하여금 해당 알고리즘을 이용하는 클라이언트로부터 독립적일수 있도록 해준다.
1.3. Motivation ¶
텍스트 스트림을 줄 단위로 나누는 많은 알고리즘들이 있다. (이하 linebreaking algorithm). 해당 알고리즘들이 그것을 필요로 하는 클래스에 긴밀하게 연결되어있는 것은 여러가지 이유 면에서 바람직하지 못하다.
- linebreaking이 필요한 클라이언트이 그 알고리즘을 직접 포함하고 있는 경우에는 클라이언트들이 더 복잡해질 수 있다. 이는 클라이언트들을 더 커지거나 유지가히 힘들게 한다. 특히 클라이언트가 여러 알고리즘을 제공해야 하는 경우에는 더더욱 그렇다.
- 각각의 알고리즘들은 상황에 따라 적절할 때가 존재한다. 클라이언트는 사용할지 안할지 모르는 알고리즘들까지 전부 필요하지 않다.
- linebreaking이 클라이언트코드의 일부인 경우, 새 알고리즘을 추가하거나, 기존 코드를 확장하기 어렵다.
Composition 클래스는 text viewer에 표시될 텍스틀 유지하고 갱신할 책임을 가진다고 가정하자. Linebreaking strategy들은 Composition 클래스에 구현되지 않는다. 대신, 각각의 Linebreaking strategy들은 Compositor 추상클래스의 subclass로서 따로 구현된다. Compositor subclass들은 다른 streategy들을 구현한다.
- SimpleCompositor - 일반적인 줄 나누기 알고리즘을 구현한다.
- TexCompositor - linebreaking 에 대해 TeX 알고리즘을 적용, 구현한다. 이 방법은 한번에 문단 전체에 대해서 전반적으로 linebreak를 최적화하려고 한다.
- ArrayCompositor - 각각의 줄에 특정 수의 단어가 들어가도록 줄나눔을 하는 알고리즘을 가진 클래스.
1.4. Applicability ¶
StrategyPattern 은 다음과 같은 경우에 이용할 수 있다.
- 많은 관련 클래스들이 오직 그들의 행동들에 의해 구분된다. Strategy들은 많은 행위중에 한가지로 상황에 따라 클래스을 설정해주는 방법을 제공해준다.
- 당신은 알고리즘의 다양함을 필요로 한다. 예를 들어, 당신이 알고리즘을 정의하는 것은 사용메모리/수행시간에 대한 trade-off (메모리를 아끼기 위해 수행시간을 희생해야 하거나, 수행시간을 위해 메모리공간을 더 사용하는 것 등의 상관관계)이다. Strategy 는 이러한 다양한 알고리즘의 계층 클래스를 구현할때 이용될 수 있다.
- StrategyPattern을 이용함으로써 복잡함이 노출되는 것과 알고리즘 구체적인 데이터 구조로 가는 것을 피할 수 있다.
- 클래스가 많은 행위들을 정의한다. 이는 다중조건문들에 의해서 구현되곤 한다. 이러한 많은 조건문들 대신, 각각 관련된 조건들을 Strategy 클래스들에게로 이동시킬 수 있다.
1.6. Participants ¶
- Strategy (Compositor)
- 모든 제공된 알고리즘에 대한 일반적인 인터페이스를 선언한다. Context는 ConcreteStrategy에 의해 구현된 알고리즘들을 호출하기 위해 이 인터페이스를 이용한다.
- 모든 제공된 알고리즘에 대한 일반적인 인터페이스를 선언한다. Context는 ConcreteStrategy에 의해 구현된 알고리즘들을 호출하기 위해 이 인터페이스를 이용한다.
- ConcreteStrategy (SimpleCompositor, TeXCompositor, ArrayCompositor)
- Strategy 인터페이스를 이용하여 알고리즘을 구현한다.
- Strategy 인터페이스를 이용하여 알고리즘을 구현한다.
- Context (Composition)
- ConcreteStrategy 객체로 설정되어진다.
- Strategy 객체의 참조를 가진다.
- Strategy 가 context의 데이터를 접근할 수 있도록 인터페이스를 정의할 수 있다.
- ConcreteStrategy 객체로 설정되어진다.
1.7. Consequences ¶
StrategyPattern 은 다음과 같은 장점과 단점을 가진다.
- 관련된 알고리즘을 묶음
- subclassing 의 대안
- 조건문을 제거하기 위한 Strategy
- 해당 구현부의 선택
- 클라이언트는 반드시 각각의 Strategy들에 대해 알아야 한다.
- Strategy 와 Context 사이의 대화중 overhead 가 발생한다.
- 객체의 수가 증가한다.
1.8. Sample Code ¶
~cpp class Composition { public: Composition (Compositor *); void Repair (); private: Compositor* _compositor; Component* _components; int _componentCount; int _lineWidth; int* _lineBreaks; int _lineCount; };
~cpp class Compositor { public: virtual int Compose ( Coord natural[], Coord stretch[], Coord shrink[], int componentCount, int lineWidth, int breaks[] ) = 0; protected: Compositor (); };
~cpp void Composition::Repair () { Coord* natural; Coord* stretchability; Coord* shrinkability; int componentCount; int* breaks; // prepare the arrays with the desired component sizes // ... // determine where the breaks are: int breakCount; breakCount = _compositor->Compose ( natural, stretchability, shrinkability, componentCount, _lineWidth, breaks ); // lay out components according to breaks // ... }
~cpp class SimpleCompositor : public Compositor { public: SimpleCompositor (); virtual int Compose ( Coord natural[], Coord stretch[], Coord shrink[], int componentCount, int lineWidth, int breaks[] ); // ... };
~cpp class TeXCompositor : public Compositor { public: TeXCompositor (); virtual int Compose ( Coord natural[], Coord stretch[], Coord shrink[], int componmentCount, int lineWidth, int breaks[] ); // ... };
{{{~cpp class ArrayCompositor : public Compositor { public: ArrayCompositor (int interval); virtual int Compose ( Coord natural[], Coord stretch[], Coord shrink[], int componentCount, int lineWidth, int breaks[] ); // ... }; {{{~cpp Composition* quick = new Composition (new SimpleCompositor); Composition* slick = new Composition (new TeXCompositor); Composition* iconic = new Composition (new ArrayCompositior (100)); }}} == Known Uses == * ET++, InterViews - line breaking algorithms as we've described. * RTL System for compiler code optimization - Register allocation, Instruction set Scheduling. * ET++ SwapsManager cacluation engine framework. * The Booch components - template arguments. - memory allocation strategies. * RApp (system for integrated circult layout) - Router Algorithms. * Borland's ObjectWindows - dialog box. validation streategies. == Releated Patterns == FlyWeightPattern : Strategy 객체는 종종 훌륭한 flyweight를 만든다. ---- ["패턴분류"]