본문 바로가기
객체지향/디자인패턴

전략 패턴

by 정재익 2026. 2. 18.

GOF 디자인 패턴의 행위 패턴중 하나이다. 

 

템플릿 메서드 패턴은 부모 클래스에 변하지 않는 템플릿을 두고, 변하는 부분을 자식 클래스에 두어서 상속을 사용한다.

전략패턴은 변하지 않는 부분을 콘텍스트에 두고 변하는 부분을 전략인터페이스를 만들고 그 인터페이스를 구현해서 문제를 해결함 상속이 아니라 위임으로 문제를 해결한다.

 

private void logic1() {
    long startTime = System.currentTimeMillis();
    //비즈니스 로직 실행
    log.info("비즈니스 로직1 실행");
    //비즈니스 로직 종료
    long endTime = System.currentTimeMillis();
    long resultTime = endTime - startTime;
    log.info("resultTime={}", resultTime);
}

private void logic2() {
    long startTime = System.currentTimeMillis();
    //비즈니스 로직 실행
    log.info("비즈니스 로직2 실행");
    //비즈니스 로직 종료
    long endTime = System.currentTimeMillis();
    long resultTime = endTime - startTime;
    log.info("resultTime={}", resultTime);
}

비즈니스와 시간측정이 합쳐있다.

 

@Slf4j
public class ContextV1 {

    public Strategy strategy;

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

    public void execute() {
        long startTime = System.currentTimeMillis();
        //비즈니스 로직 실행
        strategy.call();
        //비즈니스 로직 종료
        long endTime = System.currentTimeMillis();
        long resultTime = endTime - startTime;
        log.info("resultTime={}", resultTime);
    }
}

컨텍스트는 인터페이스를 의존한다. 

 

public interface Strategy {
    void call();
}


@Slf4j
public class StrategyLogic1 implements Strategy{
    @Override
    public void call() {
        log.info("비즈니스 로직1 실행");
    }
}

@Slf4j
public class StrategyLogic2 implements Strategy{
    @Override
    public void call() {
        log.info("비즈니스 로직2 실행");
    }
}

변하는 부분은 구현체로 설정한다.

 

@Test
void strategyV2() {
    Strategy strategyLogic1 = new Strategy() {
        @Override
        public void call() {
            log.info("비즈니스 로직1 실행");
        }
    };
    ContextV1 contextV1 = new ContextV1(strategyLogic1);
    contextV1.execute();

    Strategy strategyLogic2 = new Strategy() {
        @Override
        public void call() {
            log.info("비즈니스 로직2 실행");
        }
    };
    ContextV1 contextV2 = new ContextV1(strategyLogic1);
    contextV2.execute();
}

이렇게 익명 내부 클래스를 쓰는 것도 가능 

 

@Test
void strategyV3() {
    ContextV1 contextV1 = new ContextV1(new Strategy() {
        @Override
        public void call() {
            log.info("비즈니스 로직1 실행");
        }
    });
    contextV1.execute();

    ContextV1 contextV2 = new ContextV1(new Strategy() {
        @Override
        public void call() {
            log.info("비즈니스 로직2 실행");
        }
    });
    contextV2.execute();
}

이것도 가능 

 

@Test
void strategyV4() {
    ContextV1 contextV1 = new ContextV1(() -> log.info("비즈니스 로직1 실행"));
    contextV1.execute();

    ContextV1 contextV2 = new ContextV1(() -> log.info("비즈니스 로직2 실행"));
    contextV2.execute();
}

람다 사용 람다를 사용하려면 인터페이스에 메서드가 하나만 있어야 함

 

 

실행시점에 전략을 정하는 방법

@Slf4j
public class ContextV2 {

    public void execute(Strategy strategy) {
        long startTime = System.currentTimeMillis();
        //비즈니스 로직 실행
        strategy.call();
        //비즈니스 로직 종료
        long endTime = System.currentTimeMillis();
        long resultTime = endTime - startTime;
        log.info("resultTime={}", resultTime);
    }
}

 

의존하지 않고 파라미터로 받는다. 

 

@Test
void strategyV1() {
    ContextV2 contextV2 = new ContextV2();
    contextV2.execute(new StrategyLogic1());
    contextV2.execute(new StrategyLogic2());
}

 

클라이언트가 구현체가 고르는 것이다.

'객체지향 > 디자인패턴' 카테고리의 다른 글

데코레이터 패턴  (0) 2026.02.18
템플릿 콜백 패턴  (0) 2026.02.18
템플릿 메서드 패턴  (0) 2026.02.15
옵저버 패턴  (0) 2026.02.12
프록시 패턴  (0) 2026.01.04