ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Strategy Pattern (with iOS, Swift)
    Ray Wenderlich/Design Pattern 2020. 1. 2. 19:45

    Ch5. Strategy Pattern


    1. Strategy Pattern의 구성요소

    2. 사용 예시

    3. Delegate와 다른 점



    1. Strategy Pattern의 구성요소

    Strategy Pattern의 구성요소는 3가지로 나뉜다.


    1. Strategy를 사용할 객체

    2. Strategy를 정의하는 프로토콜

    3. 2번의 프로토콜을 구현한 Strategy객체


    <Strategy pattern의 다이어그램>



    두 개 이상의 유사한 동작이 필요하고, 이 동작이 유연하게 바뀌기를 원할 때 사용하면 좋다.

    Delegate패턴과 굉장히 유사하다. (구성요소만봐도 똑같음)


    <Delegation pattern의 다이어그램>



    2. 사용 예시

    영화 평점을 보여주는 화면이 있다고 생각해보자.

    참고로, 영화 평점은 여러 매체에서 매긴다. 로튼토마토, IMDb등


    import UIKit


    public protocol MovieRating: Strategy {

    var ratingServiceName: String { get }

    func fetchRating(for movieTitle: String, success: (_ rating: String, _ review: String) -> ())

    }


    무비 평점을 보여주기 위한 Strategy프로토콜을 정의했다.


    그러면 2개의 Strategy클래스를 만들어보자.


    1. 로튼토마토의 평점을 알려주는 Strategy

    public class RottenTomatoesClient: MovieRatingStrategy { 

    public let ratingServiceName = "Rotten Tomatoes" 


    public func fetchRating( for movieTitle: String, success: (_ rating: String, _ review: String) -> ()) { 

    // In a real service, you’d make a network request... 

    // Here, we just provide dummy values... 

    let rating = "95%" 

    let review = "It rocked!" 

    success(rating, review) 

    }

    }



    2. IMDb의 평점을 알려주는 Strategy

    public class IMDbClient: MovieRatingStrategy { 

    public let ratingServiceName = "IMDb"


    public func fetchRating( for movieTitle: String, success: (_ rating: String, _ review: String) -> ()) { 

    let rating = "3 / 10" 

    let review = """ 

    It was terrible! 

    The audience was throwing rotten tomatoes! 

    """ 

    success(rating, review) 

    }



    두 개의 Strategy를 사용하는 UIViewController

    public class MovieRatingViewController: UIViewController { 

    // MARK: - Properties 

    public var movieRatingClient: MovieRatingStrategy! 


    // MARK: - Outlets 

    @IBOutlet public var movieTitleTextField: UITextField! 

    @IBOutlet public var ratingServiceNameLabel: UILabel! 

    @IBOutlet public var ratingLabel: UILabel! 

    @IBOutlet public var reviewLabel: UILabel! 


    // MARK: - View Lifecycle 

    public override func viewDidLoad() { 

    super.viewDidLoad() 

    ratingServiceNameLabel.text = movieRatingClient.ratingServiceName


    // MARK: - Actions 

    @IBAction public func searchButtonPressed(sender: Any) { 

    guard let movieTitle = movieTitleTextField.text else { return } 


    movieRatingClient.fetchRating(for: movieTitle) { (rating, review) in 

    self.ratingLabel.text = rating self.reviewLabel.text = review

    }




    3. Delegate와 다른 점

    Strategy패턴, Delegate패턴 모두 실제 객체보다 프로토콜에 의존하기 때문에 유연함을 가진다. 

    어떤 객체도 프로토콜을 따른다면 런타임에 Strategy역할을 할 수 있게 된다.


    하지만 Delegation과 달리, Strategy 패턴은 객체의 family를 사용한다.


    Delegates는 보통 런타임에 고정된다. 예를 들어, UITableView의 delegate와 dataSource는 보통 한번 설정 된 뒤, 바뀌지 않는다.

    하지만 Strategy는 런타임에 쉽게쉽게 바꿔치기 한다.


    원문 첨부

    Use the strategy pattern when you have two or more different behaviors that are interchangeable.

    This pattern is similar to the delegation pattern: both patterns rely on a protocol instead of concrete objects for increased flexibility. Consequently, any object that implements the strategy protocol can be used as a strategy at runtime.

    Unlike delegation, the strategy pattern uses a family of objects.

    Delegates are often fixed at runtime. For example, the dataSource and delegate for a UITableView can be set from Interface Builder, and it’s rare for these to change during runtime.

    Strategies, however, are intended to be easily interchangeable at runtime. 


    ***

    Strategy Design Pattern is a type of behavioral design patterns that encapsulates a "family" of algorithms and selects one from the pool for use during runtime

    검색해보니 이런 문장이 있는데 Strategy 프로토콜을 구현한 집합체들이 있고, 그 중에 하나씩 돌려가며 쓰는 느낌인가보다. 

    이게 Delegation패턴과 가장 큰 차이점인듯?? 

    Delegate에서는 여러 옵션을 두고 하나를 골라 쓰는게 아닌 딱 올바른 로직 하나만 정해놓고 바뀌지 않는 반면,

    Strategy에서는 여러 옵션을 두고 그 때 그 때, 알맞는 옵션을 골라서 사용할 수 있도록 하는 패턴이라고 보면 되겠다.


    런타임에 바뀌고 안바뀌고 그런게 중요한게 아닌거같음 ㅋㅋ




    Key points

    You learned about the strategy pattern in this chapter. Here are its key points:

    • The strategy pattern defines a family of interchangeable objects that can be set or switched at runtime.

    • This pattern has three parts: an object using a strategy, a strategy protocol, and a family of strategy objects.

    • The strategy pattern is similar to the delegation pattern: Both patterns use a protocol for flexibility. Unlike the delegation pattern, however, strategies are meant to be switched at runtime, whereas delegates are usually fixed.

      You've laid the groundwork for Rabble Wabble to switch question strategies at runtime. However, you haven't actually created a means for the user to do this while running the app just yet! There's another pattern you'll use to hold onto user preferences like this: the singleton design pattern.

      Continue onto the next chapter to learn about the singleton design pattern and continue building out Rabble Wabble.


    'Ray Wenderlich > Design Pattern' 카테고리의 다른 글

    Observer Pattern (with Swift, Combine)  (0) 2020.02.02
Designed by Tistory.