[디자인 패턴] Strategy pattern in Swift

Ryan (Geonhee) Son·2021년 9월 18일
1

Study Stack

목록 보기
25/34

목차로 돌아가기

소개

전략 패턴은 Behavioral design pattern의 일종으로 모드가 바뀔 때마다 전략을 교체할 수 있도록 타입을 제공합니다. 전략 패턴을 적용하면 새로운 전략을 추가하더라도 기존 코드의 수정을 하지 않거나 최소화할 수 있습니다.

Example

가정

검색 기능을 개발하는 상황이라 가정합니다. 먼저, 전체, 이미지, 뉴스, 지도 검색 기능을 구현하는데, 이 경우 패턴을 적용하지 않았을 때와 적용하였을 때를 비교해보겠습니다.

패턴을 적용하지 않은 경우

패턴을 고려하지 않고 검색 기능을 구현하면 아래와 같이 작성할 수 있을 것입니다. 검색 모드를 열거형의 케이스로 정의하고, 모드 변경을 위한 메서드를 만든 후, 버튼 탭 동작에 따라 검색 모드에 따라 검색 로직을 실행하는 것입니다.

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 타입을 준수하는 새로운 검색 전략 타입을 작성하기만 하면 됩니다. 기존에 존재했던 어떤 타입, 프로퍼티, 메서드의 구현부를 수정하지 않아도 되는 것이죠.

목차로 돌아가기

참고자료

  1. Design Patterns in Swift - ochococo GitHub Repository
  2. 객체지향 디자인패턴 1 - 얄팍한 코딩사전
profile
합리적인 해법 찾기를 좋아합니다.

0개의 댓글