디자인패턴, OOP

전략 패턴(Strategy Pattern)

TedDev 2024. 8. 15. 11:19
728x90

전략 패턴(Strategy Pattern)은 소프트웨어 디자인 패턴 중 하나로, 행동 관련 디자인 패턴에 속한다. 이 패턴은 객체의 행위를 캡슐화하여 동적으로 행위를 바꿀 수 있게 해주는 패턴이다. 즉, 알고리즘을 클래스에 캡슐화하고, 런타임에 알고리즘을 선택할 수 있도록 하는 것이 전략 패턴의 핵심이다.

 

 

전략 패턴의 구조

전략 패턴은 다음과 같은 세 가지 주요 구성 요소로 이루어져 있다.

  1. Context
    • 클라이언트가 사용하는 주요 인터페이스를 제공하는 클래스
    • Context는 전략 인터페이스를 참조하고 있으며, 이를 통해 실제 전략을 실행한다.
    • 클라이언트는 Context 객체와 상호작용하며, 특정 전략을 선택할 수 있다.
  2. Strategy(전략) 인터페이스
    • 다양한 알고리즘을 정의하는 공통 인터페이스
    • 모든 구체적인 전략 클래스들은 이 인터페이스를 구현한다.
    • 전략 인터페이스는 특정 알고리즘을 수행하는 메서드를 정의한다.
  3. Concrete Strategy(구체적인 전략)
    • Strategy 인터페이스를 구현하는 구체적인 알고리즘 클래스
    • 각 클래스는 서로 다른 알고리즘 또는 행동을 구현한다.
    • Context는 이 클래스들 중 하나를 사용하여 특정 행위를 수행한다.

 

전략 패턴의 동작 방식

  1. 전략 설정 : 클라이언트는 Context 객체를 생성하고, 사용할 전략(Strategy)을 설정한다.
  2. 전략 실행 : 클라이언트가 Context 객체를 통해 요청을 하면, Context는 현재 설정된 전략 객체를 사용하여 특정 행동을 수행한다.
  3. 전략 교체 : 필요에 따라 클라이언트는 다른 전략을 설정할 수 있다. 이때 Context 객체는 새로운 전략에 맞춰 행동을 변경한다.

 

전략 패턴의 장점

  • 유연성 증가: 알고리즘을 동적으로 바꿀 수 있어 코드의 유연성이 증가한다.
  • 코드 재사용성: 공통 인터페이스를 사용하여 서로 다른 알고리즘을 캡슐화하므로 코드의 재사용성이 높아진다.
  • 유지보수 용이: 알고리즘이 변경될 때, 각 전략 클래스를 독립적으로 수정할 수 있어 유지보수가 쉽다.

 

예시

// 전략 인터페이스 정의
interface Strategy {
    public int[] execute(int[] data);
}

// 구체적인 전략 A
class ConcreteStrategyA implements Strategy {
    @Override
    public int[] execute(int[] data) {
        java.util.Arrays.sort(data);
        return data;
    }
}

// 구체적인 전략 B
class ConcreteStrategyB implements Strategy {
    @Override
    public int[] execute(int[] data) {
        java.util.Arrays.sort(data);
        int n = data.length;
        int[] reversedData = new int[n];
        for (int i = 0; i < n; i++) {
            reversedData[i] = data[n - i - 1];
        }
        return reversedData;
    }
}

// Context 클래스
class Context {
    private Strategy strategy;

    public Context(Strategy strategy) {
        this.strategy = strategy;
    }

    public void setStrategy(Strategy strategy) {
        this.strategy = strategy;
    }

    public int[] executeStrategy(int[] data) {
        return strategy.execute(data);
    }
}

// 사용 예시
public class StrategyPatternExample {
    public static void main(String[] args) {
        int[] data = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5};

        // 오름차순 정렬 전략 사용
        Context context = new Context(new ConcreteStrategyA());
        System.out.print("오름차순 정렬: ");
        printArray(context.executeStrategy(data));

        // 내림차순 정렬 전략 사용
        context.setStrategy(new ConcreteStrategyB());
        System.out.print("내림차순 정렬: ");
        printArray(context.executeStrategy(data));
    }

    public static void printArray(int[] data) {
        for (int num : data) {
            System.out.print(num + " ");
        }
        System.out.println();
    }
}
  • Strategy 인터페이스 : Strategy 인터페이스는 execute 메서드를 정의하고 있다. 이 메서드는 데이터를 입력받아 어떤 방식으로든 처리하여 반환한다.
  • ConcreteStrategyA 및 ConcreteStrategyB : 두 개의 구체적인 전략 클래스는 Strategy 인터페이스를 구현하며, 각각 오름차순 및 내림차순으로 배열을 정렬하는 로직을 구현하고 있다.
  • Context 클래스 : Context 클래스는 Strategy 인터페이스 타입의 필드를 가지고 있으며, 이를 통해 다양한 전략을 실행할 수 있다. setStrategy 메서드를 사용해 동적으로 전략을 변경할 수 있다.
  • StrategyPatternExample : main 메서드를 통해 전략 패턴을 사용하는 예시를 보여준다. Context 객체에 서로 다른 전략을 설정하고, 이를 통해 데이터를 처리하는 방식이 어떻게 달라지는지 확인할 수 있다.

 

전략 패턴의 사용 사례

전략 패턴은 여러 상황에서 유용하게 사용될 수 있다.

  • 정렬 알고리즘 : 다양한 정렬 알고리즘을 사용하는 경우 (예: 오름차순, 내림차순, 특정 기준에 따른 정렬)
  • 유저 인증 방식 : 여러 가지 인증 방식을 지원해야 하는 경우 (예: 비밀번호 인증, OAuth 인증, 생체 인증 등)
  • 가격 계산 방식 : 다양한 가격 정책(예: 할인율, 쿠폰 적용 등)을 동적으로 적용해야 하는 경우

전략 패턴을 사용하면 이러한 다양한 알고리즘을 깔끔하게 관리하고, 유연하게 교체할 수 있다.

반응형