본문 바로가기
Object-Oriented Programming/Design Pattern

Strategy Pattern

by yongmin.Lee 2022. 4. 15.

Strategy Pattern

 

 

Strategy Pattern 이란?

Strategy Pattern (전략 패턴)은 교환 가능한 객체들을 정의해두고 Strategy protocol을 이용하여 런타임에 설정하거나 변환하는 패턴

Object using a Strategy : Strategy protocol을 이용하는 객체

Strategy protocol : 모든 strategy가 반드시 구현해야 할 메서드들을 정의하고 있는 프로토콜

Strategies : Strategy 프로토콜을 준수하는 교환가능한 객체들

 

Strategy Pattern 예시코드

// MARK: - Strategy Protocol
protocol MovieRatingStrategy {
    var ratingServiceName: String { get }
    
    func fetch(fot title: String, success: @escaping ((_ rating: String, _ review: String) -> Void))
}

// MARK: - Concrete Strategy 1
class RottenTomatoesClient: MovieRatingStrategy {
    let ratingServiceName: String = "Rotten Tomatoes"
    
    func fetch(fot title: String, success: @escaping ((String, String) -> Void)) {
        // 통신을 통해 값을 받아온다고 생각합니다.
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
            let rating = "95%"
            let review = "It rocked!"
            success(rating, review)
        }
    }
}

// MARK: - Concrete Strategy 2
class IMDbClient: MovieRatingStrategy {
    let ratingServiceName: String = "IMDb"
    
    func fetch(fot title: String, success: @escaping ((String, String) -> Void)) {
        // 통신을 통해 값을 받아온다고 생각합니다.
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
            let rating = "3 / 10"
            let review = "It was terrible!"
            success(rating, review)
        }
    }
}

// MARK: - Object using a Strategy
class ViewController: UIViewController {
    
    var movieRatingClient: MovieRatingStrategy!
    
    let ratingServiceNameLabel = UILabel()
    let ratingLabel = UILabel()
    let reviewLabel = UILabel()
    
    init(movieRatingClient: MovieRatingStrategy) {
        self.movieRatingClient = movieRatingClient
        super.init(nibName: nil, bundle: nil)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        ratingServiceNameLabel.text = movieRatingClient.ratingServiceName
        
        movieRatingClient.fetch(fot: "movie title") { rating, review in
            self.ratingLabel.text = rating
            self.reviewLabel.text = review
        }
    }
}

 

Strategy Pattern 사용하는 이유

  • 정책에 따라 유연하게 동작하는 메서드를 캡슐화함으로써 정책마다 로직이 if-else 문으로 분기 하는것을 방지
  • 새로운 정책이 추가되거나 기존의 정책이 사라지더라도, 사용하는 쪽에서는 코드를 수정할 필요가 없다.
  • 기능을 사용하는 부분과 구현하는 부분을 명확히 분리한다

 

SOLID 관점에서 바라본 Strategy Pattern

  • 기능 확장에는 열려있고 변경에는 닫혀있는 개방 폐쇄 원칙(OCP)도 따르는 구조를 갖게 된다.
  • 인터페이스로 타입을 추상화하지 않았다면, 구현체를 직접 의존하게 되고 이는 두 객체간의 강한 결합으로 런타임에 메서드를 변경하지 못하게 된다. 사용객체과 구현객체 모두 추상화에 의존하게 하므로서 느슨한 결합을 가져가고 있으므로 의존성 역전 원칙(DIP)도 잘 따르고 있다고 할 수 있다.

 

 

 

 

 

참고자료

https://velog.io/@ljinsk3/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4-Strategy-Pattern

https://brunch.co.kr/@yoonms/21

'Object-Oriented Programming > Design Pattern' 카테고리의 다른 글

Factory Method Pattern, 팩토리 메소드 패턴  (0) 2022.05.09
Facade Pattern  (0) 2022.05.04
GoF Design Patterns  (0) 2022.03.14
Repository 패턴  (0) 2021.12.08
Singleton Pattern  (0) 2021.02.17