본문 바로가기

JAVA/GOF Design Pattern

GOF 스트레티지 패턴(Strategy Pattern)

SMALL

자바에서 스트레티지 패턴(Strategy Pattern)은 객체지향 디자인 패턴 중 하나로, 알고리즘군을 정의하고 각각을 캡슐화하여 상호교환이 가능하도록 만든 패턴입니다.

 

이 패턴은 알고리즘이 자주 변경되는 경우나, 유사한 알고리즘이 다양하게 적용되는 경우, 알고리즘을 사용하는 클라이언트와 독립적으로 알고리즘을 변경하고 싶은 경우에 유용합니다.

 

스트레티지 패턴은 크게 세 가지 요소로 이루어져 있습니다.

첫째는 Context(컨텍스트)입니다. 이는 알고리즘을 사용하는 역할을 합니다. 둘째는 Strategy(전략)입니다. 이는 알고리즘을 캡슐화한 인터페이스(abstract class)를 의미합니다. 셋째는 ConcreteStrategy(구체적 전략)입니다. 이는 알고리즘을 실제로 구현한 클래스를 의미합니다.

 

스트레티지 패턴을 사용하면, 알고리즘을 실행하는 코드는 컨텍스트 객체 안에 존재하며, 전략 객체들은 이 컨텍스트 객체 안에서 동적으로 교체될 수 있습니다. 이로 인해 알고리즘을 바꿀 때, 코드 수정이 필요없이 새로운 전략 객체를 생성해서 컨텍스트에 적용하면 됩니다.

 

예를 들어, 정렬 알고리즘을 구현한 경우, 컨텍스트는 배열을 정렬하는 역할을 하며, 전략 객체는 배열을 정렬하는 인터페이스를 구현한 BubbleSortStrategy, QuickSortStrategy, MergeSortStrategy 등을 말합니다. 각 전략 객체는 정렬 알고리즘을 각각 다르게 구현하고 있습니다. 컨텍스트는 사용자가 선택한 전략 객체를 통해 배열을 정렬합니다.

위의 UML 다이어그램에서, Context는 전략 객체(Strategy)를 사용하여 작업을 수행하는 클라이언트입니다. Context는 Strategy 인터페이스를 구현하는 클래스를 전략으로 사용합니다. Strategy 인터페이스는 새로운 전략 클래스를 쉽게 추가할 수 있도록 하는 역할을 합니다.

 

ConcreteStrategyA와 ConcreteStrategyB 클래스는 Strategy 인터페이스를 구현하는 전략 클래스입니다. 이전에 작성한 코드에서 AdditionStrategy, SubtractionStrategy, MultiplicationStrategy, DivisionStrategy 클래스들이 여기에 해당됩니다.

 

이제, 새로운 전략을 추가하려면 Strategy 인터페이스를 구현하는 새로운 클래스를 작성하고, Context에서 이를 전략으로 설정해주면 됩니다. 이렇게 함으로써, Context의 코드를 변경하지 않아도 새로운 전략을 추가할 수 있습니다.

 

먼저, Strategy(전략) 인터페이스를 정의합니다.

 

public interface OperationStrategy {
    int execute(int a, int b);
}

 

다음으로, ConcreteStrategy(구체적 전략)으로 덧셈, 뺄셈, 곱셈, 나눗셈을 구현한 클래스를 만듭니다.

 

public class AddStrategy implements OperationStrategy {
    public int execute(int a, int b) {
        return a + b;
    }
}

public class SubtractStrategy implements OperationStrategy {
    public int execute(int a, int b) {
        return a - b;
    }
}

public class MultiplyStrategy implements OperationStrategy {
    public int execute(int a, int b) {
        return a * b;
    }
}

public class DivideStrategy implements OperationStrategy {
    public int execute(int a, int b) {
        return a / b;
    }
}

 

마지막으로, Context(컨텍스트) 클래스를 만들어서, 필요한 연산 전략을 동적으로 교체할 수 있도록 합니다.

 

public class CalculatorContext {
    private OperationStrategy operationStrategy;

    public void setOperationStrategy(OperationStrategy operationStrategy) {
        this.operationStrategy = operationStrategy;
    }

    public int executeOperation(int a, int b) {
        return operationStrategy.execute(a, b);
    }
}

 

이제 메인 함수에서, CalculatorContext 객체를 생성하고, 필요한 연산 전략을 동적으로 교체해보겠습니다.

 

public static void main(String[] args) {
    CalculatorContext calculatorContext = new CalculatorContext();

    // 덧셈
    calculatorContext.setOperationStrategy(new AddStrategy());
    System.out.println(calculatorContext.executeOperation(10, 5)); // 15

    // 뺄셈
    calculatorContext.setOperationStrategy(new SubtractStrategy());
    System.out.println(calculatorContext.executeOperation(10, 5)); // 5

    // 곱셈
    calculatorContext.setOperationStrategy(new MultiplyStrategy());
    System.out.println(calculatorContext.executeOperation(10, 5)); // 50

    // 나눗셈
    calculatorContext.setOperationStrategy(new DivideStrategy());
    System.out.println(calculatorContext.executeOperation(10, 5)); // 2
}

 

위 코드를 실행하면, 덧셈, 뺄셈, 곱셈, 나눗셈의 결과가 출력됩니다. 이때, CalculatorContext 클래스에서는 executeOperation 메서드에서 전략 객체에 대한 호출만 처리하고 있습니다. 따라서, 새로운 연산 전략이 추가되더라도 CalculatorContext 클래스를 수정하지 않아도 됩니다. 대신, 새로운 연산 전략 클래스를 구현하고, 필요한 곳에서 전략을 설정해주면 됩니다.

이것이 스트레티지 패턴이 제공하는 유연성입니다. 전략을 캡슐화함으로써, 전략의 수정, 추가, 삭제 등을 손쉽게 처리할 수 있습니다. 또한, 이 패턴은 코드의 재사용성을 높이고, 확장성을 향상시키는 데에도 큰 도움을 줍니다.

LIST

'JAVA > GOF Design Pattern' 카테고리의 다른 글

GOF 중재자(Mediator) 패턴  (0) 2023.05.09
GOF Builder Pattern  (0) 2023.05.09
GOF Observer Pattern  (0) 2023.05.09
GOF Abstract Factory Pattern  (0) 2023.05.08
GOF Iterator 패턴  (0) 2023.04.28