💌 Design Pattern

[Design Pattern] Strategy Pattern (스트레티지패턴) with Swift

exception_log 2022. 2. 23. 19:49

Strategy Pattern 개요

Strategy는 어떤 동작을 하는 로직을 정의하고 이것들을 하나로 묶어 (캡슐화) 관리하는 패턴 
새로운 로직을 추가하거나 변경할 때 한번에 효율적으로 변경이 가능하다.

 

실제 상황에서 생각해보기

  • 스트레티지 패턴은 다양한 방식으로 특정 작업을 수행하는 클래스를 선택하고 이런 모든 알고리즘을 Strategy 라는 별도의 클래스로 추출할 것을 제안한다.
  • 예를 들어, 여행자를 위한 네비게이션 앱을 만든다고 가정해보자.
  • 앱의 첫번째 기능은 도로 위의 경로만 보여주는 기능이었다. 
  • 그러나 다음 업데이트에 도보 경로 옵션을 추가해야 하는 상황이 되었다면?
  • 그리고 다음 업데이트에 대중교통 경로까지 추가해야하는 상황이라면?
  • 게다가 또 자전거 도로까지 추가해야 한다면?!! (으악 복잡해!!)
  • 그래서 어찌저찌 기능들을 모두 추가를 하기는 했다.
  • 그런데! 만약 이런 루트들을 설정하는 클래스가 Route라는 클래스라고 했을 때, 도로 위 경로를 보여주는 알고리즘에 버그가 생겨서 코드를 수정해야 한다면, 클래스 전체에 영향을 끼쳐서 다른 코드에도 오류를 발생시킬 여지가 있다.
  • 뿐만아니라 협업의 관점에서도 문제를 일으킬 수 있다. 여러명이 하나의 클래스에 접근하여 작업을 해야하기 때문에 로직이 꼬일 여지가 있기 때문이다.
  • 이럴 때, 루트를 계산하는 알고리즘을 Strategy 클래스에 별도로 추출하여 코드를 구성한다면 문제점들이 개선될 것이다.
  • 부모 Strategy 가 있고 -> 자식 Strategy는 부모를 상속받아 구현한다. 그러나 모두 같은 부모를 가짐! 

개선 이전
Strategy Pattern 적용 후 

 

코드로 확인해보기

import XCTest

class Context {

    private var strategy: Strategy

    init(strategy: Strategy) {
        self.strategy = strategy
    }

    func update(strategy: Strategy) {
        self.strategy = strategy
    }
    
    func doSomeBusinessLogic() {
        print("Context: Sorting data using the strategy (not sure how it'll do it)\n")

        let result = strategy.doAlgorithm(["a", "b", "c", "d", "e"])
        print(result.joined(separator: ","))
    }
}

protocol Strategy {

    func doAlgorithm<T: Comparable>(_ data: [T]) -> [T]
}

class ConcreteStrategyA: Strategy {

    func doAlgorithm<T: Comparable>(_ data: [T]) -> [T] {
        return data.sorted()
    }
}

class ConcreteStrategyB: Strategy {

    func doAlgorithm<T: Comparable>(_ data: [T]) -> [T] {
        return data.sorted(by: >)
    }
}

class StrategyConceptual: XCTestCase {

    func test() {
        let context = Context(strategy: ConcreteStrategyA())
        print("Client: Strategy is set to normal sorting.\n")
        context.doSomeBusinessLogic()

        print("\nClient: Strategy is set to reverse sorting.\n")
        context.update(strategy: ConcreteStrategyB())
        context.doSomeBusinessLogic()
    }
}

 

디자인 패턴은 내일 올릴 컴포지트 패턴을 마지막으로 마무리하려고 하는데.. 

공부를 하다보니 결국 디자인 패턴은 코드의 재사용성을 증가시키거나 가독성을 증가시키거나 협업의 관점에서 긍정적인 효과를 내기 위해, 즉 유지보수하기 좋게 만드는 어떤 전략(?) 이라는 표현이 맞을까요 아무튼 그렇다는 생각이 팍 팍 드네용

 

내일 디자인패턴 마지막 글로 돌아오곘습니당!

 

감사합니다 :) 

 

오류, 문제 지적은 댓글로 달아주세요!

 

 

참고 : https://refactoring.guru/design-patterns/strategy

반응형