JAVA/JAVA Design Pattern

JAVA 전략(Strategy) 패턴

임베디드 친구 2024. 12. 30. 08:01
반응형

1. 전략(Strategy) 패턴이란?

전략 패턴(Strategy Pattern)은 특정 행동(기능)을 캡슐화하여 동적으로 변경할 수 있도록 해주는 디자인 패턴입니다. 이 패턴은 행위(Behavioral) 디자인 패턴 중 하나로, 실행 중에 알고리즘이나 로직을 바꿀 수 있게 해줍니다.

특징

  • 유연한 행동 변경: 클래스의 행동을 수정하지 않고 실행 시점에 다른 전략(알고리즘)으로 교체할 수 있습니다.
  • 인터페이스 기반 설계: 전략 패턴은 공통된 인터페이스를 제공하고, 이를 구현하여 다양한 전략을 만듭니다.
  • OCP (Open-Closed Principle): 확장에는 열려 있고, 수정에는 닫혀 있는 원칙을 따릅니다.

2. 전략 패턴의 클래스 다이어그램

+---------------------+
|      Context        |
|---------------------|
| - strategy:Strategy |
|                     |
| + setStrategy()     |
| + executeStrategy() |
+---------------------+

+---------------------+       +-------------------------+
|      Strategy       |<----->|   ConcreteStrategyA     |
|---------------------|       |-------------------------|
| + execute():void    |       | + execute():void        |
+---------------------+       +-------------------------+

+---------------------+       +-------------------------+
|   ConcreteStrategyB |       |   ConcreteStrategyC     |
|---------------------|       |-------------------------|
| + execute():void    |       | + execute():void        |
+---------------------+       +-------------------------+

설명

  1. Strategy: 공통된 행동(전략)을 정의하는 인터페이스입니다.
  2. ConcreteStrategy: Strategy를 구현한 구체적인 전략 클래스입니다.
  3. Context: 전략을 사용하는 역할로, 전략 객체를 setStrategy() 메서드를 통해 교체할 수 있습니다.

3. 전략 패턴 구현 예제

문제 상황

다양한 정렬 방식을 필요로 하는 프로그램을 가정합니다. 사용자는 실행 중에 정렬 전략(오름차순, 내림차순, 사용자 정의)을 변경할 수 있습니다.

코드 예제

// 1. 전략 인터페이스
interface SortStrategy {
    void sort(int[] numbers);
}

// 2. 구체적인 전략들
class AscendingSort implements SortStrategy {
    @Override
    public void sort(int[] numbers) {
        System.out.println("오름차순 정렬");
        Arrays.sort(numbers);
        System.out.println(Arrays.toString(numbers));
    }
}

class DescendingSort implements SortStrategy {
    @Override
    public void sort(int[] numbers) {
        System.out.println("내림차순 정렬");
        Integer[] temp = Arrays.stream(numbers).boxed().toArray(Integer[]::new);
        Arrays.sort(temp, Collections.reverseOrder());
        System.out.println(Arrays.toString(temp));
    }
}

class CustomSort implements SortStrategy {
    @Override
    public void sort(int[] numbers) {
        System.out.println("사용자 정의 정렬 (홀수 우선)");
        Arrays.sort(numbers);
        Arrays.sort(numbers, (a, b) -> (a % 2 == b % 2) ? a - b : (a % 2 == 0) ? 1 : -1);
        System.out.println(Arrays.toString(numbers));
    }
}

// 3. Context 클래스
class SortContext {
    private SortStrategy strategy;

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

    public void executeStrategy(int[] numbers) {
        if (strategy == null) {
            System.out.println("전략이 설정되지 않았습니다.");
            return;
        }
        strategy.sort(numbers);
    }
}

// 4. 테스트 코드
public class StrategyPatternExample {
    public static void main(String[] args) {
        SortContext context = new SortContext();
        int[] numbers = {5, 3, 8, 1, 2, 7};

        // 오름차순 정렬
        context.setStrategy(new AscendingSort());
        context.executeStrategy(numbers);

        // 내림차순 정렬
        context.setStrategy(new DescendingSort());
        context.executeStrategy(numbers);

        // 사용자 정의 정렬
        context.setStrategy(new CustomSort());
        context.executeStrategy(numbers);
    }
}

출력 결과

오름차순 정렬
[1, 2, 3, 5, 7, 8]
내림차순 정렬
[8, 7, 5, 3, 2, 1]
사용자 정의 정렬 (홀수 우선)
[1, 3, 5, 7, 2, 8]

4. 전략 패턴의 실제 사용 사례

  • 정렬 알고리즘 선택: 실행 시점에서 사용자나 조건에 따라 정렬 방식을 변경.
  • 데이터 압축: ZIP, RAR, TAR 등 다양한 압축 전략 적용.
  • 결제 시스템: 신용카드, PayPal, 계좌이체 등 다양한 결제 수단을 선택.
  • 그래픽 렌더링: CPU 렌더링, GPU 렌더링 등 실행 환경에 따라 렌더링 전략 변경.

5. 결론

전략 패턴은 알고리즘이나 로직을 유연하게 변경해야 할 때 매우 유용합니다. 이 패턴을 사용하면 코드 수정 없이 새로운 전략을 추가하거나 교체할 수 있어 유지보수와 확장성이 뛰어납니다.

반응형