[디자인패턴] 전략 패턴(Strategy Pattern)

이재민·2024년 4월 14일
0

디자인패턴

목록 보기
2/3

전략 패턴

전략 패턴이란, 런타임 시점에 알고리즘을 선택하여 행동을 바꿀 수 있는 행위 디자인 패턴이다.
알고리즘 변경이 빈번하게 이뤄질 때 사용하기 적합한 패턴이다.

개인적으로 실무에서 가장 유용하게 사용하고 있는 디자인 패턴 중 하나로 서비스 특성 상 변경이 빈번하게 이뤄지고 있는 상황에서 적용하기 가장 적합한 패턴이라고 생각한다.

전략 패턴을 통해 코드의 복잡성을 줄인 경험이 있고, OOP에서 강조하는 내용들을 준수하며 유지보수가 용이한 코드를 작성할 수 있다.

전략 패턴 구조

  • Context는 알고리즘을 선택할 책임이 존재하지 않는다. 다만, 클라이언트가 원하는 전략을 Context에서 등록 실행을 하며 Context는 Strategy Interface와 조합(composition)을 통해 동작을 한다.

  • 여러 알고리즘들은 Strategy를 구현하고 있으며 캡슐화되어 인터페이스로 추상화되어 있다. 그래서 Context는 개별 알고리즘에 대해 자세히 알지 못한다.

  • 새로운 알고리즘이 필요하게 된다면 Context 또는 기존 알고리즘을 수정하지 않고 새로운 알고리즘을 추가 및 수정을 할 수 있게 됩니다. 즉, OCP 원칙을 준수하게 된다.

  • 이렇듯 전략 패턴을 사용하게 된다면 OOP에서 강조하는 내용인 OCP, DIP, 상속보다는 조합, 다형성, 캡슐화 등을 준수할 수 있게 된다.

전략 패턴 주의점

  • 전략 패턴을 사용하게 되면 알고리즘 군들이 증가할 수 있다. 이는 알고리즘 객체 수가 늘어나게 되므로 관리 포인트가 증가할 수 있게 된다.
  • 알고리즘이 추후에도 많아질 것 같지 않은데 패턴을 적용하게 된다면 오히려 동료 개발자에게 복잡도를 높이는 꼴이 될 수 있다.

예제

public class StrategyPatternMain {

    public static void main(String[] args) throws IOException {

        InputStream in = System.in;
        InputStreamReader reader = new InputStreamReader(in);
        BufferedReader br = new BufferedReader(reader);

        String input = br.readLine();
        
        Context context = new Context();
        
        if ("add".equals(input)) {
            context.setStrategy(new ConcreteStrategyAdd());    
        } else if ("sub".equals(input)) {
            context.setStrategy(new ConcreteStrategySubtract());
        } else if ("mul".equals(input)) {
            context.setStrategy(new ConcreteStrategyMultiply());
        }
        
        context.executeStrategy(10, 5);
    }
}
public class Context {

    private Strategy strategy;

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

    public int executeStrategy(int a, int b) {
        return strategy.execute(a, b);
    }
}
public interface Strategy {

    int execute(int a, int b);
}

public class ConcreteStrategyAdd implements Strategy {

    @Override
    public int execute(int a, int b) {
        return a + b;
    }
}

public class ConcreteStrategySubtract implements Strategy {

    @Override
    public int execute(int a, int b) {
        return a - b;
    }
}

public class ConcreteStrategyMultiply implements Strategy {

    @Override
    public int execute(int a, int b) {
        return a * b;
    }
}

만약 spring을 사용하고 있다면 예제코드에서 보이는 setStrategy 코드를 사용하지 않고 추상화된 interface를 Collection으로 주입받아 client가 원하는 알고리즘을 Context에서 찾고 실행하게 된다면 이후 알고리즘을 추가할 때 Context 코드와 기존 알고리즘 코드는 전혀 수정할 필요가 없게된다.

앞서 말했듯이 전략 패턴을 잘 활용하게 된다면 더욱 가독성 높은 코드, 유지보수가 용이한 코드를 작성할 수 있게 된다. 현재 재직중인 회사에서도 800 라인에 가까운 코드를 단 2~3줄의 코드로 개선한 경험이 있는데 이에 대한 내용도 나중에 포스팅 할 예정이다.

참고
https://refactoring.guru/ko/design-patterns/strategy
헤드 퍼스트 디자인 패턴
https://inpa.tistory.com/entry/GOF-%F0%9F%92%A0-%EC%A0%84%EB%9E%B5Strategy-%ED%8C%A8%ED%84%B4-%EC%A0%9C%EB%8C%80%EB%A1%9C-%EB%B0%B0%EC%9B%8C%EB%B3%B4%EC%9E%90

profile
문제 해결과 개선 과제를 수행하며 성장을 추구하는 것을 좋아합니다.

0개의 댓글