본문 바로가기

디자인패턴

[디자인패턴] 전략 패턴

이번 글에서는 전략 패턴에 대해서 알아보려고 합니다.

  • 전략 패턴 개념
  • 사용예시
  • 전략 패턴 예제 코드
전략 패턴 개념

GOF 디자인패턴에서는 전략 패턴을 아래와 같이 정의하고 있습니다.

"알고리즘 제품군을 정의하고 각각을 캡슐화하여 상호 교환 가능하게 만들자. 전략을 사용하면 알고리즘을 사용하는 클라이언트와 독립적으로 알고리즘을 변경할 수 있다."

전략 패턴은 템플릿 메서드 패턴과 비슷하지만, 상속에의해 발생되는 단점들을 깔끔하게 해결 할 수 있는 패턴입니다. 즉, 템플릿 메서드 패턴은 부모클래스에 변하지 않는 템플릿을 두고, 변하는 부분을 자식클래스에서 상속을 받아 처리하였다면, 전략 패턴은 변하지 않는 부분을 Context라는 곳에 두고, 변하는 부분을 Strategy라는 인터페이스를 만들고 해당 인터페이스를 구현하도록 해서 문제를 해결하는 패턴입니다.

이러한 패턴을 사용한다면, 프로그램 실행중 미리 구현되어있는 전략을 상황에 맞게 사용 할 수 있는 장점이 있습니다.

 

사용예시

나는 어느 병원의 직원입니다. 매일 매일 환자들로 가득한 병원에서 환자의 상태에 맞게 의사를 호출해야 하는 상황에 있습니다. 예를들어, 뼈가 부러지면 외과의사에 접수를하고, 신경에 문제가 있으면 신경외과에 접수를하고, 외모에 관심이 있으신 환자분이면 성형외과에 접수를 해야합니다.

이러한 상황에 저는 execute()메소드에 미리 구현되어있는 알고리즘 전략을 파라미터값으로 넘겨 상황에 맞게 환자를 의사에게 접수하려고 합니다.

 

전략 패턴 예제 코드
@Test
void strategyV1() {
    ContextV2 context = new ContextV2();
    context.execute(new StrategyLogic1());
    context.execute(new StrategyLogic2());
}
@Slf4j
public class ContextV2 {

    public void execute(Strategy strategy) {
        enterPerson();
        strategy.call();
        outPerson();
    }

    private void enterPerson() {
        log.info("환자가 병원에 들어옴");
    }

    private void outPerson() {
        log.info("환자가 퇴원함");
    }
}

public interface Strategy {
    void call();
}

@Slf4j
public class StrategyLogic1 implements Strategy{
    @Override
    public void call() {
        log.info("외과의사 접수");
    }
}

@Slf4j
public class StrategyLogic2 implements Strategy{
    @Override
    public void call() {
        log.info("신경외과의사 접수");
    }
}

자 이제 테스트코드를 실행해보도록 하겠습니다. 테스트 코드는 아래 그림과 같이 실행 됨을 확인 할 수 있습니다.

  1. 클라이언트는 Context 를 실행하면서 인수로 Strategy 를 전달한다.
  2. Context 는 execute() 로직을 실행한다.
  3. Context 는 파라미터로 넘어온 strategy.call() 로직을 실행한다.
  4. Context 의 execute() 로직이 종료된다.

 

그렇다면 전략 패턴을 사용하는 이유는 무엇일까요??

컨텍스트 코드의 변경 없이 새로운 전략을 추가할 수 있다는 점입니다.

즉, 요구사항이 변경 되었을 때, 기존의 코드를 변경하지 않아도 된다는 점이 전략 패턴의 장점이고, 새로운 요구사항이 나올 경우에는 새로운 클래스를 만들어 관리를 하면 됩니다. 만약 추후 요구사항의 수정이 많지 않다면, 굳이 전략 패턴을 사용하지 않아도 되고, 이 패턴의 의도를 알고 활용하는 것이 더 중요하다고 생각합니다.