디자인 패턴 - Strategy pattern

어흥·2024년 5월 3일

Computer Science

목록 보기
10/28

정의

Strategy Pattern(전략)은 Algorithm Family를 정의하고 각 알고리즘을 캡슐화 한 뒤 런타임에서 알고리즘을 서로 바꿔 사용할 수 있는 디자인 패턴

  • Strategy (Compositor)
    • 지원되는 모든 알고리즘에 사용되는 공통적인 인터페이스를 정의합니다.
    • Context는 Strategy 인터페이스를 사용하여 Concrete Strategy에 정의된 알고리즘을 호출합니다.
  • Concrete Strategy
    • Strategy 인터페이스를 사용하여 알고리즘을 구현합니다.
  • Context (Composition) → TransportationToAirport
    • Concrete Strategy 객체로 구성됩니다.
    • Strategy 객체에 대한 참조를 유지합니다.
    • Strategy가 데이터에 접근 할 수 있는 인터페이스를 정의합니다.

언제 사용하면 될까?

  • 어떤 상황에서 사용할 알고리즘이 여러 개 존재할 때
  • 알고리즘을 런타임에 바꿀 수 있기 때문에 이와 같은 상황에 효과적으로 대응가능
    • 결제 시스템에서 네이버 페이, 카카오페이, 토스 페이 등 다른 알고리즘을 사용해야할 때 전략패턴을 사용할 수 있다.
    • 네비게이션에서 경로를 알려줄 때 자동차, 자전거, 도보 중에 선택하는 알고리즘에서 전략패턴 사용가능

장단점

장점

  • 런타임에서 객체 내부에서 사용되는 알고리즘을 변경 가능
  • 알고리즘을 사용하는 코드와 알고리즘을 구현하는 코드를 분리 가능
  • Open / Closed Principle(개방 폐쇄 원칙)을 준수하여 Context를 변경하지 않고도 새로운 Strategy 도입가능

단점

  • 알고리즘이 몇 개 없고 변경되는 일도 거의 없는 경우 전략 패턴의 도입이 오히려 복잡성을 증가
  • 클라이언트가 적절한 Strategy를 선택하기 위해서는 각각의 차이점 인지해야 함
  • Strategy, Context간 통신 오버헤드가 발생

구현

  1. Strategy 인터페이스 역할을 할 프로토콜을 하나 정의

    // Strategy
    protocol Strategy {
        func algorithmExecute()
    }
  2. Strategy 프로토콜을 채택하는 알고리즘 생성 → Concrete strategy

    • 자동차 경로, 도보경로, 자전거 경로
    // Concrete Strategy
    class CarRoute: Strategy {
        func algorithmExecute() {
            print("자동차 경로 찾기 완료!\n")
        }
    }
    
    // Concrete Strategy
    class WalkRoute: Strategy {
        func algorithmExecute() {
            print("도보 경로 찾기 완료!\n")
        }
    }
    
    // Concrete Strategy
    class BikeRoute: Strategy {
        func algorithmExecute() {
            print("자전거 경로 찾기 완료!\n")
        }
    }
  3. 알고리즘들을 교체해가며 사용할 Context를 구현

    // Context
    class Navigation {
        private var routeAlgorithm: Strategy?
        
        func execute() {
            self.routeAlgorithm?.algorithmExecute()
        }
        
        func setStrategy(strategy: Strategy) {
            self.routeAlgorithm = strategy
        }
    }
  1. 사용

    let navigation = Navigation()
    navigation.setStrategy(strategy: CarRoute())
    navigation.execute()
    
    navigation.setStrategy(strategy: WalkRoute())
    navigation.execute()
    
    navigation.setStrategy(strategy: BikeRoute())
    navigation.execute()
    
    // 자동차 경로 찾기 완료!
    // 도보 경로 찾기 완료!
    // 자전거 경로 찾기 완료!

0개의 댓글