개념
SOLID 원칙 중 개방폐쇄의 원칙에 따라 확장에 대해서는 개방적이고 변경에 대해서는 폐쇄적으로
기존의 코드를 변경하지 않으면서 기능을 추가할 수 있도록 고안된 디자인 패턴이다.
변경될 것(전략)과 변하지 않는 것을 구분하여 두 모듈이 만나는 지점에 인터페이스를 정의해
인터페이스에 의존하도록 코드를 작성한다.
전략 패턴을 이용하는 역할을 수행하는 컨텍스트가 필요에 따라 구체적인 전략을 바꿀 수 있도록
의존관계를 주입하며, 전략은 인터페이스나 추상 클래스로 외부에서 동일한 방식으로 호출할 수 있게
하며, 콘크리트 전략은 전략을 실제로 구현한 클래스를 의미한다.
장점
- 알고리즘을 캡슐화해 실행 중에 동적으로 바꿀 수 있다.
- 새로운 변경이 기존의 코드에 영향을 미치지 않는다.
- 전략은 독립적으로 사용될 수 있어, 다른 클래스에서도 재사용할 수 있다.
- 독립적이기 때문에 테스트가 용이하다.
- 의존관계를 역전시켜 확장성 있는 코드를 만들 수 있다.
- 각 알고리즘을 별도의 클래스로 분리하여 코드를 읽기 쉽고 유지보수가 용이하다.
단점
- 전략 패턴을 사용할 때마다 새로운 구현 클래스를 만들어야 한다.
- 전략 패턴을 사용하기 위해 의존성을 주입해야 하기 때문에 과한 의존 관계가 형성 될 수 있다.
- 구현이 어려워 적절한 분석과 설계가 필요하다.
- 런타임 시에 알고리즘을 선택하기 때문에 추가적인 오버헤드가 발생할 수 있다.
- 추가적인 클래스와 인터페이스가 필요해 코드가 복잡해질 수 있다.
사용하는 이유
if (분기1) {
} else if (분기2) {
} else if (분기3) {
} else if (분기4) {
// 만약 이 중간에 새로운 분기를 추가하거나
// 분기가 수십 수백가지라면?
} else if (분기5) {
} else if (분기6) {
} else if (분기7) {
}
...
else {
}
조건문을 사용한 분기처리는 변경과 확장 시 코드가 복잡해지고 수정이 불편하고 실수가 발생할 확률이 높다.
= 유지보수에 유리하지 않다.
알고리즘의 변경이 빈번한 경우에 전략 패턴을 사용해 효율적으로 적용할 수 있다.
예시
interface Strategy {
do();
}
class ConcreteStrategyA implements Strategy {
do();
}
class ConcreteStrategyZ implements Strategy {
do();
}
...
class ConcreteStrategyZ implements Strategy {
do();
}
class Context {
Strategy strategy;
void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
void do() {
this.strategy.do();
}
}
전략의 추상화와 이를 구현한 다양한 전략 구현 클래스
그리고 전략을 등록하고 실행하는 컨텍스트로 이루어져 있다.
기타
템플릿 메소드 패턴과의 차이점
- 전략 패턴은 컴포지션 방식을 템플릿 메소드 패턴은 상속을 사용한다.
- 전략 패턴은 알고리즘 자체를 캡슐화 한다면 템플릿 메서드 패턴은 알고리즘의 일부 단계만 변경한다.
- 전략 패턴은 실행 중에 동적으로 알고리즘 교환이 가능하지만 템플릿 메소드 패턴은 고정되어 있다.
'CS' 카테고리의 다른 글
CPU 작동 원리 (1) | 2023.10.09 |
---|---|
고정 소수점과 부동 소수점 (0) | 2023.10.09 |
ARM 프로세서 (0) | 2023.10.09 |