본문 바로가기
설계/디자인패턴

[디자인패턴] 템플릿 메서드(Template Method) 패턴 이해하기

by J4J 2024. 4. 22.
300x250
반응형

안녕하세요. J4J입니다.

 

이번 포스팅은 템플릿 메서드 (Template Method) 패턴에 대해 적어보는 시간을 가져보려고 합니다.

 

 

 

Template Method 패턴이란?

 

template method 패턴은 상위 클래스에서 공통으로 사용되는 템플릿을 제공하여 하위 클래스에서 구체적인 단계를 재 정의할 수 있도록 도와줍니다.

 

template method의 기본 구조는 다음과 같습니다.

 

Template Method 구조

 

 

 

구조를 보시면 상위 클래스에서는 공통으로 재 사용될 수 있는 메서드 (= Template Method)를 제공하고 있습니다.

 

그리고 하위 클래스 별로 상세 로직을 정의할 수 있도록 추상 메서드 (= Primitive Method)를 제공하고 있습니다.

 

 

반응형

 

 

개인적으로 template method는 구조만 확인하더라도 어떤 목적으로써 사용되는지 한 눈에 확인되는 디자인 패턴 중 하나인 것으로 생각합니다.

 

구조를 보고 이해되시는 것처럼 동일한 목적을 가지는 공통 기능을 가지고 있어야 하지만 일부 기능들에 대해서는 서로 다른 비즈니스 로직이 필요하다고 생각한다면 template method를 사용은 여러 선택지 중 한 개가 될 수 있습니다.

 

 

 

template method를 사용하지 않는다면 각각의 기능 처리가 필요할 때 분기를 나누는 행위를 해야 할 수 있습니다.

 

예를 들어 다음과 같은 소스 코드가 작성될 수 있습니다.

 

public void method() {
    // 공통 기능 처리
    
    // 타입 별 기능 처리
    switch(type) {
        // A 타입 정의
        // B 타입 정의
    }
    
    // 공통 기능 처리
}

 

 

 

이런 코드를 작성하는 것이 자연스러운 행위일 수 있지만 위와 같은 타입 별 기능 처리를 하는 구간이 많아지거나, 분기 처리되어야 하는 타입들이 많아진다면 결국 확장성 있는 개발을 하기 어렵게 만듭니다.

 

매번 타입이 추가되거나 삭제될 때 공통으로 사용되는 기능들을 변경해야 되기 때문에 예상치 못한 다양한 문제들도 발생시킬 수 있습니다.

 

 

 

 

해당 상황에서 만약 소스 코드가 다음과 같이 변경된다고 가정해보겠습니다.

 

public void method() {
    // 공통 기능 처리
    
    primitiveMethod();
    
    // 공통 기능 처리
}

public void primitiveMethod();

 

 

 

코드가 위와 같이 변경된다면 매번 타입의 변경 사항에 대해 고려하지 않게 될 것이고 결국 확장성이 개발을 하게 될 겁니다.

 

즉, 타입 별 상세 로직이 더 많이 필요하게 되더라도 전체적인 구조에 영향을 주는 상황은 발생하지 않게 됩니다.

 

 

 

 

Template Method 패턴 특징

 

template method 패턴의 특징은 다음과 같습니다.

 

 

 

[ 장점 ]

 

  • 상위 클래스가 가지고 있는 구조를 재 사용할 수 있음
  • 새로운 유형에 대한 확장성이 좋아짐
  • 하위 클래스만이 가지고 있는 로직에 대해 집중할 수 있음
  • 템플릿을 기반으로 원하는 부분만 재 정의하여 사용할 수 있음

 

 

 

 

[ 단점 ]

 

  • 상위 클래스에 의존되어 있기 때문에 공통 로직이 변경되는 경우 하위 클래스들에 영향도를 검토해야 함
  • 정해진 템플릿에 의존되어 있기 때문에 전체 구조를 벗어나는 행위를 할 수 없음
  • 필요한 하위 클래스만큼 클래스 파일의 개수가 증가함

 

 

 

template method의 가장 큰 특징은 결국 oop의 추상화와 다형성이라고 얘기해 볼 수 있습니다.

 

추상 메서드를 선언하여 하위 클래스에서 정의를 하도록 제공하고 있으며, 동일한 상위 클래스를 이용한 다형성의 특징도 확인해 볼 수 있습니다.

 

 

 

 

Template Method 패턴 예시 (1) - Before

 

이번엔 template method를 활용한 간단한 예시를 작성해 보겠습니다.

 

먼저 template  method 패턴을 적용하지 않는 경우입니다.

 

// shape
package com.jforj.templatemethod.before;

public class Shape {

    public void printShape(String type, int width, int height, int radius) {
        System.out.println("print common shape.");

        System.out.println("calculate area");
        int area = 0;
        switch (type) {
            case "circle": {
                area = radius * radius;
                break;
            }

            case "rectangle": {
                area = width * height;
                break;
            }
        }

        System.out.println("area of shape is " + area);
    }
}


// main
package com.jforj.templatemethod.before;

public class Main {
    public static void main(String[] args) {
        Shape circle = new Shape();
        circle.printShape("circle", 0, 0, 3);

        Shape rectangle = new Shape();
        rectangle.printShape("rectangle", 4, 3, 0);
    }
}

 

 

 

 

원과 직사각형이 모두 소유할 수 있는 도형의 넓이에 대해 계산을 해야 되는 상황에서 위와 같은 코드가 작성될 수 있습니다.

 

하지만 각 도형마다 특징들을 가지고 있기 때문에 특징들을 고려하여 넓이를 구하는 코드가 작성되어야 합니다.

 

그러다 보니 모든 경우를 고려한 비즈니스 로직이 한 곳에 담기게 되고 확장성이 좋지 않은 코드가 된 것을 확인할 수 있습니다.

 

 

 

 

Template Method 패턴 예시 (2) - After

 

이번엔 위의 코드에서 template method 패턴을 적용해 보겠습니다.

 

// shape
package com.jforj.templatemethod.after;

public abstract class Shape {
    public void printShape() {
        System.out.println("print common shape.");

        System.out.println("calculate area");
        int area = calculate();

        System.out.println("area of shape is " + area);
    }

    public abstract int calculate();
}


// circle
package com.jforj.templatemethod.after;

public class Circle extends Shape {
    private int radius;

    public Circle(int radius) {
        this.radius = radius;
    }

    @Override
    public int calculate() {
        return radius * radius;
    }
}


// rectangle
package com.jforj.templatemethod.after;

public class Rectangle extends Shape {
    private int width;
    private int height;

    public Rectangle(int width, int height) {
        this.width = width;
        this.height = height;
    }

    @Override
    public int calculate() {
        return width * height;
    }
}


// main
package com.jforj.templatemethod.after;

public class Main {
    public static void main(String[] args) {
        Shape circle = new Circle(3);
        circle.printShape();

        Shape rectangle = new Rectangle(4, 3);
        rectangle.printShape();
    }
}

 

 

 

코드를 보시면 상위 클래스를 기반으로 하위 클래스 별 특징들을 각각 정의하여 코드가 작성된 것을 확인할 수 있습니다.

 

다른 타입들이 가지고 있어야 하는 불필요한 정보들도 모두 제거되고 하위 클래스에서 필요한 것에만 집중되어 구체적인 정의가 된 것도 볼 수 있습니다.

 

 

 

 

 

 

 

 

이상으로 템플릿 메서드 (Template Method) 패턴에 대해 간단하게 알아보는 시간이었습니다.

 

읽어주셔서 감사합니다.

 

 

 

728x90
반응형

댓글