의도
어떤 행동을 수행하기 위한 캡슐화된 알고리즘을 정의하고 이를 전략적으로 변경하면서 활용하기 위해 사용하는 패턴
활용
- 조건문을 이용한 알고리즘 변경으로 인한 유리관리의 어려움을 개선하기 위해
- 필요한 알고리즘이 다양한 경우
- 필요한 알고리즘의 선택이 runtime에 이뤄져야 하는 경우
- 클래스 간의 차이점이 행위(알고리즘) 만 존재하는 경우
설계방법
Composition
Delegation
구조의 이해
전략패턴의 알고리즘은 ConcreteStrategy 를 의미하며 알고리즘의 교체는 ConcreteStrategy 의 교체를 의미합니다.
Strategy 에 해당하는 인터페이스를 만들고 이를 ConcreteStrategy 에서 구현하고 Context 에서 ConcreteStrategy 를 변경하면서 객체를 통한 알고리즘 교체를 가능하게 합니다.
전략 패턴 상에서 새로운 알고리즘을 위한 클래스 생성이 필요한 경우,
필요한 클래스를 선언하고 인터페이스에 정의 된 행위 (Operation)을 클래스에 구현함으로써 Context에서의 알고리즘 추가 사용을 가능하게 합니다.
예시
아래 예시처럼 전략패턴을 구현했다고 가정해 봅시다.
Unit 객체는 AttackBehavior 라는 행위객체를 가지고 있고, 공격방식 ( Shot, Magic, Physical) 클래스를 통해 AttackBehavior 인터페이스를 수현하고 있습니다.
알고리즘의 교체는 Context 에 해당하는 Unit 객체에서 일어나며, Unit 에서 어떤 행위가 발생하는 경우 아래처럼 알고리즘을 교체해 줄 수 있게 됩니다.
// magic attack
ab = new MagicAttack();
ab.attack();
// physical attack
ab = new PhysicalAttack();
ab.attack();
Unit 관점에서는 조건문을 사용해서 알고리즘을 교체하는 것과의 차이가 모호할 수 있을 것 같습니다.
전략패턴의 장점은 Unit class를 상속받는 하위 클래스가 만들어 질 때 조금 더 명확해지는데요, 아래 예시를 보시죠.
Unit 을 상속받는 세부 유형의 클래스가 만들어 지는 경우에, Unit 조건을 체크해 가면서 알고리즘을 선택하는 것이 아닌
AttackBehavior에 객체를 셋팅해 주는 것 만으로도 행위를 전략적으로 결정할 수 있게 됩니다.
class Magician extends Unit {
public Magician(){
ab = new MagicAttack();
}
}
위 코드처럼 Magician 이 생성될 때 자동으로 기본 공격을 MagicAttack 으로 설정할 수 있어서 알고리즘 교체/설정을 용이하게 해주는 장점이 있습니다. ( 코드는 필요한 내용을 담았을 뿐 동작하는 코드는 아닙니다. )