디자인패턴

전략패턴

마지막한조각 2022. 7. 8. 14:23
  • 템플릿 메서드 패턴의 상속 문제를 위임으로 해결한다.
    전략 패턴에서 Context 는 변하지 않는 템플릿 역할을 하고, Strategy 는 변하는 알고리즘 역할을 한다
        
  • GOF 디자인 패턴에서 정의한 전략 패턴의 의도는 다음과 같다.
        > 알고리즘 제품군을 정의하고 각각을 캡슐화하여 상호 교환 가능하게 만들자. 전략을 사용하면 알고리즘을
        사용하는 클라이언트와 독립적으로 알고리즘을 변경할 수 있다.
        
  • 전략 패턴의 핵심은 Context 는 Strategy 인터페이스에만 의존한다는 점이다. 덕분에 Strategy 의
        구현체를 변경하거나 새로 만들어도 Context 코드에는 영향을 주지 않는다.
        
  • 이 방식의 단점은 Context 와 Strategy 를 조립한 이후에는 전략을 변경하기가 번거롭다는 점이다. 물론
        Context 에 setter 를 제공해서 Strategy 를 넘겨 받아 변경하면 되지만, Context 를 싱글톤으로
        사용할 때는 동시성 이슈 등 고려할 점이 많다.

 

  • 해결책은 매개변수로 코드조각을 넘겨 받아서 Context가 execute()를 실행 시 파라미터로 넘어온 call()을 사용하게 하는 방법.
public static void main(String[] args) {
    //전략패턴 적용
    /*Context context = new Context(new StrategyImpl());
    context.execute();*/

    //인터페이스에 메서드가 1개라면 람다식 사용가능
    //익명 내부 클래스를 사용해도 가능하지만 그렇게하면 너무 코드가 길어짐.
/*    Context lamda = new Context(()->{
        TemplateMethod.sleep(1000);
        System.out.println("실행2");
    });
    lamda.execute();*/

    //실행할 때 마다 전략을 유연하게 변경할 수 있다.
    //단점 역시 실행할 때 마다 전략을 계속 지정해주어야 한다는 점이다.
    Context context = new Context();
    context.execute(() -> System.out.println("실행3"));
    context.execute(() -> System.out.println("실행4"));



}

//변하는 알고리즘 역할을 한다.
interface Strategy {
    public void call();
}


//전략패턴에서 Context(문맥)은 변하지 않는 것을 뜻한다.
static class Context {
    private Strategy strategy;

    public Context() {
    }

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

    public void execute() {
        //부가적인 로직
        long startTime = System.currentTimeMillis();
        //핵심로직
        strategy.call();
        //핵심로직 end
        long endTime = System.currentTimeMillis();
        long executeTime = endTime - startTime;
        System.out.println("실행에 소요되는 시간 : " + executeTime);
    }

    // 콜백을 활용하는 전략패턴
    public void execute(Strategy strategy) {
        //부가적인 로직
        long startTime = System.currentTimeMillis();
        //핵심로직
        strategy.call();
        //핵심로직 end
        long endTime = System.currentTimeMillis();
        long executeTime = endTime - startTime;
        System.out.println("실행에 소요되는 시간 : " + executeTime);
    }
}

//해당 전략에 따라 바꿀 수 있는 변하는 부분의 구현체
static class StrategyImpl implements Strategy {
    @Override
    public void call() {
        TemplateMethod.sleep(1000);
        System.out.println("실행1");
    }
}

static class StrategyImpl2 implements Strategy {
    @Override
    public void call() {
        TemplateMethod.sleep(1000);
        System.out.println("실행2");
    }
}

 

 

인프런 김영한님의 스프링 핵심 원리 고급편 강의를 보며 정리했습니다.

 

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B3%A0%EA%B8%89%ED%8E%B8

 

스프링 핵심 원리 - 고급편 - 인프런 | 강의

스프링의 핵심 원리와 고급 기술들을 깊이있게 학습하고, 스프링을 자신있게 사용할 수 있습니다., - 강의 소개 | 인프런...

www.inflearn.com