Lee's Grow up

[디자인패턴/Design Pattern] Template Method 패턴 / 템플릿 메소드 패턴 본문

PROGRAMMING/디자인패턴

[디자인패턴/Design Pattern] Template Method 패턴 / 템플릿 메소드 패턴

효기로그 2019. 11. 21. 15:53
반응형

관련 내용은 [자바 언어로 배우는 디자인 패턴 입문] 이라는 책의 공부 내용을 개인적으로 정리한 내용입니다.
처음 배우는 부분이기 때문에 틀린 부분이 있다면 지적해주시면 감사하겠습니다.

1. Template Method 패턴이란?


동작 상의 알고리즘의 프로그램 뼈대를 정의하는 행위 디자인 패턴으로써, 알고리즘의 구조를 변경하지 않고 알고리즘의 특정 단계를 다시 정의할 수 있게 해주는 패턴방식.

즉, 공통되는 부분은 추상클래스로 정의된 상위 클래스에서 구현을하고, 재정의가 필요한 부분은 추상메소드로 선언합니다.

2. Template Method 패턴의 등장 인물


이번 포스팅에서 사용될 요소들의 역할입니다.

  • AbstractClass ( 추상 클래스 ) 의 역할
    1. 템플릿 메소드를 구현하고, 그 템플릿 메소드에서 사용하는 추상 메소드를 선언합니다.
    2. 추상 메소드는 하위 클래스인 ConcreateClass 역할에 의해 구현됩니다.
  • ConcreteClass ( 구현 클래스 ) 의 역할
    1. AbstractClass 역할에서 정의되어 있는 추상 메소도를 구체적으로 구현합니다.
    2. 구현한 메소드는 AbstractClass역의 템플릿 메소드에서 호출됩니다.
Template Method 패턴의 클래스 다이어그램

3. 예제


이제 Template Method의 예제로 좀 더 내용을 구체화 해보겠습니다.

예제에서 사용될 클래스 다이어그램

Animal 클래스

추상 클래스로써 name(), bark() 는 추상메소드로 정의하고, display()메소드만 구현해놨습니다.

public abstract class Animal {
    public abstract void name();
    public abstract void bark();

    public final void display() {
        name();
        bark();
    }
}

Dog 클래스

앞서 추상클래스로 정의한 Animal클래스를 상속받아서 추상 메소드들을 재정의 해줍니다.

public class Dog extends Animal{
    @Override
    public void name() {
        // TODO Auto-generated method stub
        System.out.println("name : dog");
    }
    @Override
    public void bark() {
        // TODO Auto-generated method stub
        System.out.println("bowwow!!");
    }
}

Cat 클래스

앞서 추상클래스로 정의한 Animal클래스를 상속받아서 추상 메소드들을 재정의 해주고, 추가로 walk()메소드를 추가합니다.

public class Cat extends Animal{
    @Override
    public void name() {
        // TODO Auto-generated method stub
        System.out.println("name : cat");
    }

    @Override
    public void bark() {
        // TODO Auto-generated method stub
        System.out.println("meow meow");
        System.out.println("meow meow");
    }

    public void walk() {
        System.out.println("산책 따위");
    }
}

Main 클래스

public class Main {
    public static void main(String[] args) {
        Animal a1 = new Dog();
        Animal a2 = new Cat();

        a1.display();
        a2.display();
    }
}
실행 결과
name : dog
bowwow!!
name : cat
meow meow
meow meow
람다로 리팩토링

위 예제에서 기존에 cat에는 walk() 메서드가 추가되었습니다. 해당 메서드는 () -> void 의 시그니처를 가지기 때문에 해당 시그니처를 가지는 인터페이스를 추가해줍니다.

@FunctionalInterface
public interface TemplateFunctionalInterface {
    void display();
}

그다음 Animal클래스를 조금 수정해줍니다.

public abstract class Animal {
    public abstract void name();
    public abstract void bark();

    public final void display(TemplateFunctionalInterface templateFunctionalInterface) {
        name();
        bark();
        templateFunctionalInterface.display();
    }
}

마지막으로 사용 단계에서 필요한 로직을 구현해줍니다.

public static void main(String[] args) {
        Animal a1 = new Dog();
        Animal a2 = new Cat();

        a1.display(()-> System.out.println("산책을 좋아합니다"));
        a2.display(()->System.out.println("산책 따위"));
    }
그렇다면 왜 이렇게 사용하는 것일까?

이유는 간단합니다.

  1. 로직을 공통화 합니다.
    • Template Method를 사용하지 않고 공통되는 로직을 모든 클래스에 복사&붙여넣기로 작성했다고 가정합니다. 이때 공통 로직중 치명적인 오류가 발생해서 수정해야 하는 상황이 생긴다면?? 해당 디자인 패턴을 사용할 경우, AbstractClass의 공통 로직 부분만 수정하면 되는 반면, 복사&붙여넣기는 모든 클래스에 해당 로직을 수정해야합니다.
  2. 하위 클래스를 상위 클래스와 동일시한다.
    • Dog클래스와 Cat클래스는 서로 다른 타입이지만 하나의 Animal이라는 타입에 대입이 가능합니다. 이때 instanceof등으로 하위 클래스의 종류를 특정하지 않아도 프로그램이 작동하도록 만드는게 좋습니다.

4. 관련 패턴


  1. Factory Method 패턴 : Template Method 패턴을 인스턴스 생성에 응용한 패턴 link
  2. Strategy 패턴 : Template Method처럼 상속으로 흐름을 컨트롤하는게 아닌, 위임 을 통해 알고리즘 전체를 완전히 바꾸는 방식 link

5. 비교하기


디자인 패턴을 배우다 보니까Strategy ,Template Method가 얼핏 보면 비슷하다고 느낌이 들어서 차이점을 정리합니다.

  • Strategy : 알고리즘을 구성으로 사용.유연성link
  • Template Method : 알고리즘을 서브클래스에서 일부 지정할 수 있으면서 재사용이 가능, 하지만 의존성이 크다는 문제가 발생.재사용link
반응형
Comments