전략 패턴은 Behavioral design pattern의 일종으로 모드가 바뀔 때마다 전략을 교체할 수 있도록 타입을 제공합니다. 전략 패턴을 적용하면 새로운 전략을 추가하더라도 기존 코드의 수정을 하지 않거나 최소화할 수 있습니다.
검색 기능을 개발하는 상황이라 가정합니다. 먼저, 전체, 이미지, 뉴스, 지도 검색 기능을 구현하는데, 이 경우 패턴을 적용하지 않았을 때와 적용하였을 때를 비교해보겠습니다.
패턴을 고려하지 않고 검색 기능을 구현하면 아래와 같이 작성할 수 있을 것입니다. 검색 모드를 열거형의 케이스로 정의하고, 모드 변경을 위한 메서드를 만든 후, 버튼 탭 동작에 따라 검색 모드에 따라 검색 로직을 실행하는 것입니다.
final class SearchFeatureWithoutPattern {
enum Mode {
case all, image, news, map
}
private var mode: Mode = .all
func setMode(to mode: Mode) {
self.mode = mode
}
func searchButtonTapped() {
switch mode {
case .all:
print("전체 검색")
case .image:
print("이미지 검색")
case .news:
print("뉴스 검색")
case .map:
print("지도 검색")
}
}
}
let searchFeatureWithoutPattern = SearchFeatureWithoutPattern()
searchFeatureWithoutPattern.setMode(to: .news)
searchFeatureWithoutPattern.searchButtonTapped()
하지만 이 경우에는 동영상 검색과 같이 새로운 검색 전략을 추가하고자 할 때 Mode
에 새로운 케이스를 추가하고 searchButtonTapped()
메서드를 직접 수정하여야 합니다. 확장성이 떨어지는 것이죠. 또한 프로젝트 이해도가 떨어지는 상황에서 기존에 개발해둔 기능을 수정하려 한다면 리스크가 클 수 있습니다.
반면 전략 패턴을 적용하여 동일한 기능을 구현하면 아래와 같이 작성할 수 있습니다. 각 전략을 타입으로써 구성하고 전략 타입들이 가져야할 최소한의 인스턴스 메서드 인터페이스를 프로토콜로 정의하여 이를 준수하도록 하는 것입니다. 프로토콜에 의해 구현 상 다형성을 보장하기에 각 전략 타입의 상세 구현은 각 타입에서 해주면 됩니다. 검색 전략의 변경은 setSearchStrategy(to:)
메서드를 통해 어떤 검색 전략 타입을 따를지 설정해줄 수 있습니다.
final class SearchFeatureWithPattern {
private var searchStrategy: SearchStrategy = SearchStrategyAll()
func setSearchStrategy(to strategy: SearchStrategy) {
searchStrategy = strategy
}
func searchButtonTapped() {
searchStrategy.search()
}
}
protocol SearchStrategy {
func search()
}
struct SearchStrategyAll: SearchStrategy {
func search() {
print("전체 검색")
}
}
struct SearchStrategyImage: SearchStrategy {
func search() {
print("이미지 검색")
}
}
struct SearchStrategyNews: SearchStrategy {
func search() {
print("뉴스 검색")
}
}
struct SearchStrategyMap: SearchStrategy {
func search() {
print("지도 검색")
}
}
let searchFeatureWithPattern = SearchFeatureWithPattern()
searchFeatureWithPattern.setSearchStrategy(to: SearchStrategyNews())
searchFeatureWithPattern.searchButtonTapped()
이러한 상황에서 새로운 검색 전략을 추가하고자 한다면 단순히 SearchStrategy
타입을 준수하는 새로운 검색 전략 타입을 작성하기만 하면 됩니다. 기존에 존재했던 어떤 타입, 프로퍼티, 메서드의 구현부를 수정하지 않아도 되는 것이죠.