변혁적인 삶

[SW공학 | 디자인패턴] 9. 전략 패턴 (Strategy Pattern) 본문

SW공학/디자인패턴

[SW공학 | 디자인패턴] 9. 전략 패턴 (Strategy Pattern)

revolutionarylife 2024. 11. 10. 12:12
반응형

⚙️ [SW공학 | 디자인패턴] 9. 전략 패턴 (Strategy Pattern)

목차

  • 전략 패턴 개요
  • 전략 패턴의 필요성
  • 전략 패턴의 구조
  • 전략 패턴 예제
  • 전략 패턴의 장점과 단점
  • 마무리

전략 패턴 개요

안녕하세요! 오늘은 알고리즘을 동적으로 변경하거나 교체할 수 있는 전략 패턴(Strategy Pattern)에 대해 알아보겠습니다. 전략 패턴은 행동 패턴(Behavioral Pattern) 중 하나로, 동일한 작업을 수행하는 여러 알고리즘이 필요할 때 유용하게 사용할 수 있습니다.

전략 패턴은 객체의 행동을 동적으로 설정할수 있게 하며, 조건에 따라 적합한 전략을 선택하고 교체할 수 있도록 합니다. 즉, 알고리즘을 필요에 따라 동적으로 변경하여 유연한 설계를 가능하게 합니다.


전략 패턴의 필요성

특정 작업을 수행하는 여러 방식이 필요할 때, 코드에 조건문이 많아지면 유지보수가 어려워집니다. 전략 패턴은 다양한 알고리즘을 하나의 인터페이스로 묶어 관리함으로써, 동적으로 알고리즘을 변경할 수 있습니다.

예를 들어, 결제 시스템에서 카드 결제, 계좌이체, 포인트 결제 등 다양한 결제 방식이 있다면, 전략 패턴을 사용하여 결제 방식을 쉽게 변경할 수 있습니다.


전략 패턴의 구조

전략 패턴은 Strategy (전략 인터페이스), ConcreteStrategy (구체적인 전략), Context (전략을 사용하는 클래스)로 구성됩니다.

  • Strategy (전략 인터페이스)
    • 각 전략이 공통으로 사용할 인터페이스를 정의합니다.
  • ConcreteStrategy (구체적인 전략)
    • `Strategy` 인터페이스를 구현하여 구체적인 알고리즘이나 동작을 정의합니다.
  • Context (전략을 사용하는 클래스)
    • `Strategy` 인터페이스를 사용하여 특정 전략을 호출합니다. `Context` 클래스는 클라이언트가 전략을 설정하고 사용할 수 있도록 도와줍니다.

전략 패턴 예제

아래 예제는 전략 패턴을 사용하여 결제 방식(카드 결제, 계좌이체, 포인트 결제)을 동적으로 설정하고 호출하는 예제입니다.

// Strategy 인터페이스
interface PaymentStrategy {
    void pay(int amount);
}

// ConcreteStrategy 1: 카드 결제
class CardPayment implements PaymentStrategy {
    @Override
    public void pay(int amount) {
        System.out.println("카드로 " + amount + "원 결제합니다.");
    }
}

// ConcreteStrategy 2: 계좌 이체 결제
class BankTransferPayment implements PaymentStrategy {
    @Override
    public void pay(int amount) {
        System.out.println("계좌 이체로 " + amount + "원 결제합니다.");
    }
}

// ConcreteStrategy 3: 포인트 결제
class PointPayment implements PaymentStrategy {
    @Override
    public void pay(int amount) {
        System.out.println("포인트로 " + amount + "원 결제합니다.");
    }
}

// Context 클래스: 결제 시스템
class PaymentContext {
    private PaymentStrategy paymentStrategy;

    // 결제 전략 설정 메서드
    public void setPaymentStrategy(PaymentStrategy paymentStrategy) {
        this.paymentStrategy = paymentStrategy;
    }

    // 결제 처리 메서드
    public void executePayment(int amount) {
        paymentStrategy.pay(amount);
    }
}

// 클라이언트 코드
public class StrategyPatternExample {
    public static void main(String[] args) {
        PaymentContext context = new PaymentContext();

        // 카드 결제
        context.setPaymentStrategy(new CardPayment());
        context.executePayment(10000);

        // 계좌 이체 결제
        context.setPaymentStrategy(new BankTransferPayment());
        context.executePayment(15000);

        // 포인트 결제
        context.setPaymentStrategy(new PointPayment());
        context.executePayment(5000);
    }
}

출력 결과

카드로 10000원 결제합니다.
계좌 이체로 15000원 결제합니다.
포인트로 5000원 결제합니다.

예제 설명

  1. PaymentStrategy 인터페이스 (Strategy): 결제 방식에 공통으로 필요한 pay() 메서드를 정의합니다.
  2. CardPayment, BankTransferPayment, PointPayment (ConcreteStrategy): 각각의 결제 방식을 구현하는 구체적인 전략 클래스입니다.
  3. PaymentContext (Context): setPaymentStrategy() 메서드로 클라이언트가 원하는 결제 전략을 설정하며, executePayment() 메서드에서 선택된 전략의 pay() 메서드를 호출하여 결제를 수행합니다.

전략 패턴의 장점과 단점

장점

  • 유연성 증가: 런타임에서 다양한 전략을 설정할 수 있어, 조건문 없이 동적으로 행동을 변경할 수 있습니다.
  • 코드 재사용성: 구체적인 전략 클래스를 재사용할 수 있어 코드 중복이 줄어듭니다.
  • 단일 책임 원칙(SRP) 준수: 전략 클래스를 분리함으로써 각 클래스는 하나의 책임만 가지며, 유지보수가 용이합니다.

단점

  • 클래스 수 증가: 전략 패턴을 사용하면 각 전략마다 별도의 클래스를 만들어야 하므로 코드가 복잡해질 수 있습니다.
  • 전략 간 의존성: 전략 클래스가 서로 의존하거나 공유 데이터가 필요한 경우, 구현이 어려워질 수 있습니다.

마무리

전략 패턴은 행동을 동적으로 설정하여 유연하게 사용할 수 있는 디자인 패턴입니다. 코드의 복잡성을 줄이고 다양한 전략을 쉽게 추가하거나 교체할 수 있는 방법을 제공하므로, 조건문을 줄이고 모듈성을 높이는 데 유용합니다. 전략 패턴을 활용하여 효율적인 설계를 구현해보세요! ⚙️

반응형