디자인패턴

Stractegy Pattern - 전략 패턴

빈코더 2024. 12. 28. 11:26
728x90

Stractegy Pattern - 전략 패턴

전략 패턴이란?

전략 패턴(Strategy Pattern)은 행위 디자인 패턴(Behavioral Design Pattern) 중 하나로, 알고리즘 군을 정의하고 각각을 캡슐화하여 상호 교환 가능하게 만드는 패턴입니다. 이를 통해 클라이언트는 알고리즘을 독립적으로 변경할 수 있으며, 코드의 유연성과 확장성을 높일 수 있습니다.

여기서 '전략'이란 일종의 알고리즘이 될 수 도 있으며, 기능이나 동작이 될 수도 있는 특정한 목표를 수행하기 위한 행동 계획을 말합니다.
즉, 어떤 일을 수행하는 알고리즘이 여러가지 일때, 동작들을 미리 전략으로 정의함으로써 손쉽게 전략을 교체할 수 있는, 알고리즘 변형이 빈번하게 필요한 경우에 적합한 패턴입니다.

전략 패턴의 개념

  1. Strategy(전략): 알고리즘을 수행하는 인터페이스를 정의합니다.
  2. Concrete Strategy(구체적인 전략): Strategy 인터페이스를 구현하여 실제 알고리즘을 제공합니다.
  3. Context(문맥): Strategy 객체를 포함하며, 클라이언트가 설정한 전략을 실행하는 역할을 합니다.

전략 패턴의 구조

  [Context] -- uses --> [Strategy]
                            ^
                            |
              +-------------+-------------+
              |             |             |
  [ConcreteStrategyA] [ConcreteStrategyB] [ConcreteStrategyC]

전략 패턴의 장단점

  • 장점
    • 유연한 알고리즘 교체: 런타임 시에 알고리즘을 자유롭게 교체할 수 있습니다.
    • 코드 중복 감소: 알고리즘을 별도의 클래스로 분리하여 코드 중복을 방지합니다.
    • 개방-폐쇄 원칙(OCP) 준수: 새로운 알고리즘을 추가하더라도 기존 코드를 수정하지 않고 확장할 수 있습니다.
  • 단점
    • 클래스 수 증가: 알고리즘마다 별도의 클래스를 생성해야 하므로 클래스의 수가 늘어날 수 있습니다.
    • 복잡성 증가: 전략을 설정하고 관리하는 코드가 추가되어 복잡성이 증가할 수 있습니다.

전략 패턴의 적용사례

  • 정렬 알고리즘 선택: 다양한 정렬 알고리즘을 상황에 따라 선택적으로 적용할 때.
  • 데이터 압축 방식 선택: 파일 압축 시 다양한 알고리즘을 적용할 때.
  • 경로 탐색 알고리즘: 네비게이션 시스템에서 최단 경로, 최적 경로 등을 선택할 때.

전략 패턴의 예제

  // Strategy 인터페이스
  interface PaymentStrategy {
      fun pay(amount: Int)
  }

  // Concrete Strategy A
  class CreditCardPayment(private val cardNumber: String) : PaymentStrategy {
      override fun pay(amount: Int) {
          println("Paid $$amount using Credit Card ending with ${cardNumber.takeLast(4)}")
      }
  }

  // Concrete Strategy B
  class PayPalPayment(private val email: String) : PaymentStrategy {
      override fun pay(amount: Int) {
          println("Paid $$amount using PayPal account $email")
      }
  }

  // Context 클래스
  class ShoppingCart {
      private var paymentStrategy: PaymentStrategy? = null

      fun setPaymentStrategy(strategy: PaymentStrategy) {
          paymentStrategy = strategy
      }

      fun checkout(amount: Int) {
          paymentStrategy?.pay(amount) ?: println("Payment strategy not set")
      }
  }

  // 사용 예시
  fun main() {
      val cart = ShoppingCart()

      // 신용카드 결제
      cart.setPaymentStrategy(CreditCardPayment("1234-5678-9012-3456"))
      cart.checkout(100)

      // 페이팔 결제
      cart.setPaymentStrategy(PayPalPayment("user@example.com"))
      cart.checkout(200)
  }
  • 이 예제에서 PaymentStrategy는 결제 방법을 정의하는 인터페이스이며, CreditCardPayment와 PayPalPayment는 각각 신용카드와 페이팔 결제를 구현한 클래스입니다.
  • ShoppingCart는 PaymentStrategy를 사용하여 결제를 처리하며, 런타임에 결제 방식을 자유롭게 변경할 수 있습니다.

결론

전략 패턴은 다양한 알고리즘을 유연하게 적용하고 교체할 수 있도록 도와주는 강력한 도구입니다. 이를 통해 코드의 유지보수성과 확장성을 높일 수 있습니다.

728x90