빨간색코딩

Template Method Pattern (템플릿 메소드 패턴, hook 메소드, 예제) 본문

디자인패턴

Template Method Pattern (템플릿 메소드 패턴, hook 메소드, 예제)

빨간색소년 2018. 2. 26. 21:39

jdbcTemplate, restTemplate 등 스프링에서 지원하는 많은 템플릿들을 보았다. 이런 것들은 기계적이며 길고 반복적인 코드들을 깔끔하게 처리해준다. (ex. jdbc 코드를 짤때 커넥션부터해서 close까지의 그 긴 코드를 몇 줄만으로도 똑같은 기능을 할 수 있는..) 이런 것들이 바로 템플릿 메소드 패턴이 적용된 좋은 예제들이다.(근데 더 알아보니까 다른 디자인패턴이라는 듯...ㅜ) 가져다 쓰기만 하면 재미없으니 탐구를 해보자ㅋㅋ

1. 템플릿메소드 패턴은 왜 쓰는가?


네이버 이미지에서 따온 사진이다. 이것만큼 템플릿을 잘 설명할 수 없을 것 같다ㅋㅋㅋ 이 템플릿 자를 사용하면 누구나 똑같은 네모세모를 찍어낼 수 있다. 템플릿메소드도 이와 무관하지 않다. 상위 클래스(추상 클래스)에서는 템플릿에 해당하는 메소드들이 정의되어 있고, 하위 클래스에서 이를 상속받아 메소드를 구현하는 것이다. 이렇게하면 연관된 것들끼리 뼈대를 통일할 수 있고, 하위 클래스에서 코드량이 매우 줄어들고 핵심로직만 작성할 수 있다.

2. 사용 예제 먼저보기

아래에는 무선, 로봇 청소기가 있다.

무선청소기 WirelessVacuum.java

public class WirelessVacuum {
    private int battery = 0;

    public void charge(int count) {
        if (battery < 100) {
            System.out.println("충전중...");
            battery += count;
        } else {
            System.out.println("충전완료!!");
        }
    }

    public void run() {
        System.out.println("전원 ON : 부릉");
        System.out.println("모터 시동 : 부릉부릉");
        System.out.println("흡입 시작 : 위이이잉");
        while (battery > 0) {
            System.out.println("슈우우우우욱~~~!");
            battery--;
        }
    }
}

로봇청소기 RoboticVacuum.java

public class RoboticVacuum {
    private int battery = 0;

    public void charge(int count) {
        if (battery < 100) {
            System.out.println("충전중...");
            battery += count;
        } else {
            System.out.println("충전완료!!");
        }
    }

    public void run() {
        System.out.println("전원 ON : Hello world!");
        System.out.println("모터 시동 : 띠용");
        System.out.println("흡입 시작 : 조용..");
        while (battery > 0) {
            System.out.println("센서로 위치파악");
            System.out.println("이동!");
            System.out.println("조용하게 슉");
            battery--;
        }
    }
}

청소기 사용 유저 VacuumClient.java

public class VacuumClient {
    public static void main(String[] args) {
        WirelessVacuum cleaner1 = new WirelessVacuum();
        RoboticVacuum cleaner2 = new RoboticVacuum();

        System.out.println("=== 무선청소기 start ===");
        cleaner1.charge(2);
        cleaner1.run();
        System.out.println("=== 무선청소기 end ===");
        
        System.out.println("=== 로봇청소기 start ===");
        cleaner2.charge(2);
        cleaner2.run();
        System.out.println("=== 로봇청소기 end ===");
    }
}

패턴 적용

위의 코드에서 반복코드가 발생하고 있다. 템플릿 메소드 패턴을 적용해보자.

VacuumTemplate.java

public abstract class VacuumTemplate {
    private int battery = 0;
    
    // 일반메소드(=Hook 메소드) : 구현해도되고 안해도 되고..
    public void charge(int count) {
        if (battery < 100) {
            System.out.println("충전중...");
            battery += count;
        } else {
            System.out.println("충전완료!!");
        }
    }
    
    // 템플릿 메소드
    public void run() {
        prepareRun();
        while (battery > 0) {
            working();
            battery--;
        }	
    }
    
    // 추상메소드 : 하위클래스에서 무조건 구현해야함
    abstract void prepareRun();
    abstract void working();
}

WirelessVacuum.java

public class WirelessVacuum extends VacuumTemplate {
    @Override
    void prepareRun() {
        System.out.println("전원 ON : 부릉");
        System.out.println("모터 시동 : 부릉부릉");
        System.out.println("흡입 시작 : 위이이잉");
    }

    @Override
    void working() {
        System.out.println("슈우우우우욱~~~!");
    }
}

RoboticVacuum.java

public class RoboticVacuum extends VacuumTemplate {
    @Override
    void prepareRun() {
        System.out.println("전원 ON : Hello world!");
        System.out.println("모터 시동 : 띠용");
        System.out.println("흡입 시작 : 조용..");
    }

    @Override
    void working() {
        System.out.println("센서로 위치파악");
        System.out.println("이동!");
        System.out.println("조용하게 슉");
    }
}

살펴보기

VacuumTemplate 를 보면 반복되는 코드를 아주 예쁘게 처리하고, 달라질 수 있는 부분에 한해서만 하위클래스에서 꼭 구현하도록 abstract 키워드를 붙여 추상메소드를 만들어 주었다. 하위 클래스에서는 이 추상메소드만 구현한다면, Client쪽에서 같은 결과를 볼 수 있는 것이다.

  • Hook 메소드 : 상황에 맞게 정의하거나 안해도 된다.
  • 템플릿 메소드 : 공통적인 로직이 들어가며, 하위클래스마다 달라질 수 있는 부분은 추상메소드를 박아둔다.

예제 출력 결과

=== 무선청소기 start ===
충전중...
전원 ON : 부릉
모터 시동 : 부릉부릉
흡입 시작 : 위이이잉
슈우우우우욱~~~!
슈우우우우욱~~~!
=== 무선청소기 end ===
=== 로봇청소기 start ===
충전중...
전원 ON : Hello world!
모터 시동 : 띠용
흡입 시작 : 조용..
센서로 위치파악
이동!
조용하게 슉
센서로 위치파악
이동!
조용하게 슉
=== 로봇청소기 end ===


Comments