개발 이야기/디자인 패턴

[디자인 패턴] 템플릿 메소드(Template Method) 패턴이란?

제이온 (Jayon) 2021. 3. 11.

안녕하세요? 제이온입니다.

 

저번 시간에는 전략 패턴에 대해서 알아 보았습니다. 오늘은 템플릿 메소드 패턴을 설명하겠습니다.

 

 

템플릿 메소드(Template Method) 패턴

GoF의 디자인 패턴에 의하면, 템플릿 메소드 패턴을 아래와 같이 정의합니다.

 

 

알고리즘의 구조를 메소드에 정의하고, 하위 클래스에서 알고리즘 구조의 변경없이 알고리즘을 재정의 하는 패턴이다. 알고리즘이 단계별로 나누어 지거나, 같은 역할을 하는 메소드이지만 여러곳에서 다른형태로 사용이 필요한 경우 유용한 패턴이다.

 

 

토비의 스프링에 의하면, 템플릿 메소드 패턴을 아래와 같이 정의합니다.

 

 

상속을 통해 슈퍼클래스의 기능을 확장할 때 사용하는 가장 대표적인 방법. 변하지 않는 기능은 슈퍼클래스에 만들어두고 자주 변경되며 확장할 기능은 서브클래스에서 만들도록 한다.

 

 

둘다 하위 클래스에서 사용되지만, 변하지 않는 기능을 상위 클래스에 저장해 놓고, 확장할 기능은 서브 클래스에서 만들도록 설계한다는 내용을 담고 있습니다.

 

 

템플릿 메소드(Template Method) 패턴의 예제

 

 

템플릿 메소드의 전체적인 구조는 위와 같습니다. AbstractClass는 템플릿 메소드를 정의하며, 하위 클래스에서 알맞게 확장할 수 있는 메소드인 훅 메소드를 제공합니다. 여기서, 템플릿 메소드는 일반적인 메소드와 훅 메소드를 이용합니다. 그리고 ConcreteClass는 물려받은 훅 메소드를 재정의하는 역할을 합니다.

 

 

이제, 실제 예제를 봅시다. 만약, 두 개의 라면을 끓이는 과정이 아래와 같다고 가정합시다.

 

 

신라면 너구리
1. 물을 끓인다.
2. 면을 넣는다.
3. 계란을 넣는다.
4. 4분 기다린다.
1. 물을 끓인다.
2. 면을 넣는다.
3. 콩나물을 넣는다.
4. 5분 기다린다.

 

 

이를 한 번 생각나는대로 코딩해 보겠습니다.

 

 

public class ShinRamen {
    public void boilWater() {
        System.out.println("물을 끓인다.");
    }

    public void putNoodles() {
        System.out.println("면을 넣는다.");
    }

    public void putEgg() {
        System.out.println("계란을 넣는다.");
    }

    public void waitForMinutes() {
        System.out.println("4분 기다린다.");
    }
}

 

 

위 코드는 신라면 조리 방법입니다.

 

 

public class RaccoonRamen {
    public void boilWater() {
        System.out.println("물을 끓인다.");
    }

    public void putNoodles() {
        System.out.println("면을 넣는다.");
    }

    public void putBeanSprouts() {
        System.out.println("콩나물을 넣는다.");
    }

    public void waitForMinutes() {
        System.out.println("5분 기다린다.");
    }
}

 

 

위 코드는 너구리 조리 방법입니다.

 

 

보시면 알겠지만, 물을 끓이는 것과 면을 넣는 행위는 완전히 동일한 코드입니다. 따라서, Ramen이라는 클래스를 정의하여 중복된 코드를 제거할 수 있습니다.

 

 

 

 

위와 같은 구조를 보일 것입니다. 하지만, 여전히 추가로 '무언가'를 넣는 행위와 'x분' 기다린다는 행위가 유사합니다. 템플릿 메소드 패턴은 이것도 추상화하는 것이 목표입니다.

 

 

public abstract class Ramen {

    public void makeRamen() {
        boilWater();
        putNoodles();
        putExtra();
        waitForMinutes();
    }

    public void boilWater() {
        System.out.println("물을 끓인다.");
    }

    public void putNoodles() {
        System.out.println("면을 넣는다.");
    }

    public abstract void putExtra();

    public abstract void waitForMinutes();
}

 

 

Ramen 클래스를 추상 클래스로 선언한 다음, 추상화할 메소드 2개를 추상 메소드로 선언합니다. 여기서 makeRamen()은 템플릿 메소드이고, putExtra()와 waitForMinutes()는 훅 메소드라고 볼 수 있습니다.

 

 

public class ShinRamen extends Ramen {

    @Override
    public void putExtra() {
        System.out.println("계란을 넣는다.");
    }

    @Override
    public void waitForMinutes() {
        System.out.println("4분 기다린다.");
    }
}

 

 

ShinRamen 클래스는 Ramen을 상속받아와서 추상 메소드를 재정의합니다.

 

 

public class RaccoonRamen extends Ramen {

    @Override
    public void putExtra() {
        System.out.println("콩나물을 넣는다.");
    }

    @Override
    public void waitForMinutes() {
        System.out.println("5분 기다린다.");
    }
}

 

 

RaccoonRamen 클래스는 Ramen을 상속받아와서 추상 메소드를 재정의합니다.

 

 

 

 

결과적으로는 위와 같은 구조를 갖게 됩니다.

 

 

정리

템플릿 메소드 패턴은 알고리즘의 뼈대를 맞추는 것을 목표로 합니다. 즉, 전체적인 레이아웃을 통일하지만 상속받은 클래스는 훅 메소드를 이용하여 확장할 수 있도록 유연성을 주는 디자인 패턴이라고 할 수 있습니다.

 

 

출처

개발자가 반드시 정복해야 할 객체 지향과 디자인 패턴 - 최범균

 

 

템플릿 메서드 패턴(Template Method Pattern)

템플릿 메서드 패턴(Template Method Pattern) 어떤 작업을 처리하는 일부분을 서브 클래스로 캡슐화해 전체 일을 수행하는 구조는 바꾸지 않으면서 특정 단계에서 수행하는 내역을 바

www.crocus.co.kr

 

 

 

디자인패턴 - 템플릿 메소드 패턴

개요 객체지향 디자인 패턴 중 템플릿 메소드 패턴에 대해 알아본다. AbstractMap 에 사용된 템플릿 메소드 패턴을 살펴본다. 템플릿 메소드 패턴 구현시 추상클래스가 아닌 인터페이스를 사용하면

yaboong.github.io

 

댓글

추천 글