Strategy Pattern
태그 :
- 개념
- - 알고리즘을 교체해서 동일한 문제를 다른 방법으로 해결 하는 패턴
I. 의도
다양한 알고리즘이 존재하면 이들 각각을 하나의 클래스로 캡슐화해 알고리즘의 대체가 가능하도록 한다. 클라이언트와 독립적인 다양한 알고리즘으로 변형할 수 있다. 알고리즘이 변경되어도 클라이언트는 변경할 필요없다
정의 : 알고리즘을 교체해서 동일한 문제를 다른 방법으로 해결 하는 패턴
: 알고리즘군을 정의하고 각각을 캡슐화하여 바꿔 쓸 수 있게 만듦, 레지스터할당방법, 명령어 집합 스캐듈링 전략
II. 활용
- 행위들이 조금씩 다를 뿐 개념적으로 관련된 많은 클래스들이 존재하는 경우, 각각의 서로 다른 행위별로 클래스를 작성한다. 즉, 개념에 해당하는 클래스는 하나만 정의하고 서로 다른 행위들을 별도의 클래스로 만드는 것이다
- 알고리즘의 변형이 필요한 경우에 사용할 수 있다
- 사용자가 모르고 있는 데이터를 사용해야 하는 알고리즘이 필요할 때
- 많은 행위를 정의하기 위해 클래스 안에 복잡한 다중 조건문을 사용해야 하는 경우 선택문보다는 starategy클래스 이용이 바람직
III. 결과
- 관련 알고리즘의 군을 형성한다. 상속을 통해 알고리즘 공통의 기능성을 추출하고 재사용할 수 있다
- 서브클래싱을 사용하지 않는 다른 방법이다. 상속은 다양한 알고리즘이나 행위를 지원하는 또 다른 방법이다 – 알고리즘을 starategy 클래스로 독립시키면 context와 무관하게 알고리즘을 변형/이해/확장이 용이하다
- strategy는 조건문을 없앨 수 있다
- 구현의 선택이 가능하다 – 동일한 행위에 대해 다른 구현을 제공할 수 있다
- 사용자는 서로 다른 전략을 알고 있어야 한다 – 클라이언트가 서로 다른 행위의 특성을 알고 있는 경우 starategy 사용
- strategy와 context 클래스 간에 과다한 메시지가 전송된다
- 객체 수가 증가한다
관련 패턴: starategy 객체는 작은 규모의 클래스들이므로 flyweight 패턴으로 정의하는 것이 좋다
Strategy: 제공하는 모든 알고리즘에 대한 공통의 오퍼레이션들을 인터페이스로 정의한다. Context 클래스는 ConcreteStrategy 클래스에 정의한 인터페이스를 통해서 실제 알고리즘을 사용한다.
- ConcreteStrategy: Strategy 인터페이스를 실제 알고리즘으로 구현한다.
- Context: ConcreteStrategy 객체가 무엇인지 구체화한다. 즉, Strategy 객체에 대한 참조자를 관리하고, 실제로는 Strategy 서브클래스의 인스턴스를 갖고 있음으로써 구체화한다. 또한 Strategy 가 자료에 접근해가는데 필요한 인터페이스를 정의한다.
소스코드
/StrategyExample test application
class StrategyExample {
public static void main(String[] args) {
Context context;
// Three contexts following different strategies
context = new Context(new ConcreteStrategyAdd());
int resultA = context.executeStrategy(3,4);
context = new Context(new ConcreteStrategySubtract());
int resultB = context.executeStrategy(3,4);
context = new Context(new ConcreteStrategyMultiply());
int resultC = context.executeStrategy(3,4);
}
}
// The classes that implement a concrete strategy should implement this
// The context class uses this to call the concrete strategy
interface Strategy {
int execute(int a, int b);
}
// Implements the algorithm using the strategy interface
class ConcreteStrategyAdd implements Strategy {
public int execute(int a, int b) {
System.out.println("Called ConcreteStrategyAdd's execute()");
return a + b; // Do an addition with a and b
}
}
class ConcreteStrategySubtract implements Strategy {
public int execute(int a, int b) {
System.out.println("Called ConcreteStrategySubtract's execute()");
return a - b; // Do a subtraction with a and b
}
}
class ConcreteStrategyMultiply implements Strategy {
public int execute(int a, int b) {
System.out.println("Called ConcreteStrategyMultiply's execute()");
return a * b; // Do a multiplication with a and b
}
}
// Configured with a ConcreteStrategy object and maintains a reference to a Strategy object
class Context {
private Strategy strategy;
// Constructor
public Context(Strategy strategy) {
this.strategy = strategy;
}
public int executeStrategy(int a, int b) {
return strategy.execute(a, b);
}
}