이론 공부!/디자인 패턴

[디자인패턴] 템플릿 메서드 패턴 과 전략 패턴의 비교

TutleKing 2023. 6. 24. 23:18

새로 입사한 회사에서 프로그래밍 중 제가 템플릿 메서드 패턴과 전략 패턴을 구분 없이 사용하고 있다 라는 피드백을 받았습니다.

사실 디자인 패턴에 대해 공부를 해보지 않았기 때문에 이 기회를 삼아 한번 정리해보고자 합니다.

 

제가 회사에서 보았던 코드는 아래와 같이 입력된 값에 의해서 구현체가 달라지는 상황이 었습니다. 

아래 코드를 보고 무슨 패턴이지? 라고 생각이 드신다면 이 글을 보시며 함께 공부하면 좋겠습니다! 

public class Main {
    public static void main(String[] args) {
        String input = "a";

        Strategy strategy;
        if (input.equals("a")) {
            strategy = new StrategyClass1();
        } else {
            strategy = new StrategyClass2();
        }

        strategy.run();
    }
}

 

Template method pattern

우선 템플릿이란 정해진 형식 이라고 정의할 수 있습니다. 그러므로 어떠한 정해진 형식에 의해 코드를 구성할 수 있게 하는 패턴이라고 이해 했습니다.

  • 상위 클래스에서 알고리즘의 골격을 정의하고 하위 클래스에서 일부 단계를 구체화 하는 패턴
  • 알고리즘의 전체적인 구조는 상위 클래스에서 정의되고, 구체적인 구현은 하위 클래스에서 가능하도록 하는 패턴

Strategy pattern

전략이라는 워딩이 아주 일반적이지만 어떠한 코드를 전략적으로 효율화 한다는 느낌으로 이해했습니다.

  • 알고리즘을 캡슐화하여 런타임에 동적으로 알고리즘을 변경할 수 있다는 특징이 있는 패턴

두 패턴의 차이점

아래 표와 같이 큰 차이점으로는 상속구현 의 차이로 볼 수 있다.

  템플릿 메서드 패턴 전략 패턴
목적 재사용 촉진 : 상위 클래스의 일부 단계를 하위 클래스가 위임 받아 재사용 가능 유연성 확보 : 알고리즘을 캡슐화 하여 동적으로 교환이 가능하도록 함
설계 방식 상속 (extends) 구현 (implements)
확장성 상위 클래스를 수정하지 않아도 단계를 추가할 수 있음 새로운 전략을 추가할 경우 클래스를 하나 더 만들어야함

 

그렇다면 실제 코드로서 확인 해보고자 합니다. 

 

템플릿 메서드 패턴 class 

abstract class TemplateMethod {
    // 위에서 언급하는 알고리즘 골격에 해당하는 메서드 
    public void templateMethod() {
        commonStep();
        specificStep();
    }

    public void commonStep() {
        System.out.println("TemplateMethod.commonStep");
    }
    
    // 사용자가 직접 구현해야하는 메서드
    abstract void specificStep();
}

class ConcreteClass1 extends TemplateMethod {

    @Override
    void specificStep() {
        System.out.println("ConcreteClass1.specificStep");
    }
}

class ConcreteClass2 extends TemplateMethod {

    @Override
    void specificStep() {
        System.out.println("ConcreteClass2.specificStep");
    }
}

 

전략 패턴 class 

interface Strategy {
   // 사용자가 구현을 해야만 하는 메서드 정의
    void run();
}

class StrategyClass1 implements Strategy{
    @Override
    public void run() {
        System.out.println("StrategyClass1.run");
    }
}

class StrategyClass2 implements Strategy{
    @Override
    public void run() {
        System.out.println("StrategyClass2.run");
    }
}

 

실행 코드

public class Main {
    public static void main(String[] args) {
        TemplateMethod class1 = new ConcreteClass1();
        class1.templateMethod();

        System.out.println();

        TemplateMethod class2 = new ConcreteClass2();
        class2.templateMethod();

        System.out.println();

        Strategy strategy1 = new StrategyClass1();
        strategy1.run();
        System.out.println();

        Strategy strategy2 = new StrategyClass2();
        strategy2.run();
    }
}

결과

TemplateMethod.commonStep
ConcreteClass1.specificStep

TemplateMethod.commonStep
ConcreteClass2.specificStep

StrategyClass1.run

StrategyClass2.run

 

위와 같이 정리하며 느낀 가장 큰 차이점은 상속과 구현의 차이였고, 회사에서 직접 맞닿은 코드는 런타임때에 사용해야하는 알고리즘들이 바뀌었기 때문에 전략 패턴을 사용하는 것이라고 이번 기회를 통해 명확하게 배웠습니다. 

 

반응형