전략 패턴과 템플릿 메서드 패턴은 유사하지만 다른 의도를 가지고 있다.
템플릿 메서드 패턴은 부모 클래스에 변하지 않는 템플릿을 두고, 변하는 부분을 자식 클래스에서 상속을 사용해 해결하였지만, 전략 패턴은 변하지 않는 코드 영역을 Context에 두고, 변하는 부분을 Strategy라는 인터페이스를 만들고 해당 인터페이스를 구현하도록 하여 문제를 해결한다.
즉 템플릿 메서드 패턴의 템플릿 역할을 Context가 하고, Strategy는 자식을 클래스에서 상속을 이용해 처리하는 부분을 인터페이스로 변경하였다.
알고리즘 제품군을 정의하고 각각을 캡슐화하여 상호 교환 가능하게 만들자. 전략을 사용하면 알고리즘을 사용하는 클라이언트와 독립적으로 알고리즘을 변경할 수 있다 [GOF 전략 패턴]
Strategy 인터페이스를 정의하는데, 이 부분은 변하는 코드의 역할을 맡는다.
public interface Strategy {
void call();
}
Strategy 인터페이스를 정의했다면 Context를 지정하여야 한다.
@Slf4j
public class ContextExample{
private Strategy strategy;
public ContextExample(Strategy strategy){
this.strategy = strategy;
}
public void execute(){
//비지니스 로직 실행
strategy.call();
//비지니스 로직 종료
}
public void execute(Strategy strategy){
//비지니스 로직 실행
strategy.call();
//비지니스 로직 종료
}
}
Context(문맥)은 변하지 않지만 그 문맥 안에서 strategy를 통해 일부 전략이 변경된다.
전략 패턴의 핵심은 Context는 단지 Strategy인 인터페이스에만 의존한다는 점이다. 그렇기 때문에 해당 구현체를 변경하거나 수정하여도 Context의 코드에 영향을 주지 않는다. Spring을 많이 공부했다면 익숙할 수 있다. 바로 스프링에서 의존관계 주입에서 사용하는 방식이기 때문이다.
@Test
void strategy(){
ContextExample context1 = new ContextExample(() -> log.info("비지니스 로직1 실행"));
context1.execute();
ContextExample context2 = new ContextExample(() -> log.info("비지니스 로직2 실행"));
context2.execute();
}
또한 함수형 인터페이스의 사용으로 사용하는 코드가 람다식의 사용으로 매우 간결해질 수 있다는 것도 장점 중 하나이다.
public void execute(){
//비지니스 로직 실행
strategy.call();
//비지니스 로직 종료
}
public void execute(Strategy strategy){
//비지니스 로직 실행
strategy.call();
//비지니스 로직 종료
}
전략 패턴에서 생각해보아야 할 점은 Context의 내부 필드에 Strategy를 가지고 있다는 점이다. 만약 DI를 통해 전략을 주입받고 실행하는 방식에는 이후로는 전략을 런타임에 변경하기가 매우 어렵다.
스프링으로 애플리케이션을 개발할 때 애플리케이션 로딩 시점에 의존관계 주입을 통해 필요한 의존관계를 모두 맺고 요청을 처리하는 원리와 같다.
물론 중간에 런타임에 전략을 변경할 수 있는 로직을 추가할 수 있지만 Context가 싱글톤인 경우 동시성 이슈 등 고려할 점이 많다. 그렇기에 실시간으로 변경해야 한다면 Context를 새로 생성하고 새로운 전략을 주입받아 사용하는 것이 더 안전할 수 있다.
위 코드의 메서드 중 인자로 전략을 전달받는 경우에는 다르다. Context의 내부 필드에 존재하지 않고 클라이언트 측에서 전략을 선택하여 인자로 넘겨 실행하면 원하는 시점에 원하는 전략을 사용할 수 있기에 좀 더 유연하다고 할 수 있다.
'디자인 패턴' 카테고리의 다른 글
데코레이터 패턴 + [F] (0) | 2022.02.19 |
---|---|
빌더 패턴 + [F] (0) | 2022.02.19 |
데코레이터 패턴 (0) | 2022.01.21 |
프록시 패턴 (0) | 2022.01.20 |
템플릿 메서드 패턴 (0) | 2022.01.15 |
댓글