본문 바로가기
SWE/C++ OOP

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

by S나라라2 2021. 10. 17.
반응형

Template Method Pattern 템플릿 메소드 패턴

 

개념

템플릿 메소드 패턴이란 메소드에서 알고리즘의 골격을 정의한다. 그리고 알고리즘의 여러 단계 중 일부는 서브 클래스에서 처리한다.

 

예시

커피 만드는 법과 홍차 만드는 법은 같은 알고리즘을 가지고 있다. 

커피 만드는 법 홍차 만드는 법
1) 물을 끓인다.
2) 끓는 물에 커피를 우려낸다.
3) 커피를 컵에 따른다.
4) 설탕과 우유를 추가한다.
1) 물을 끓인다.
2) 끓는 물에 차를 우려낸다.
3) 차를 컵에 따른다.
4) 레몬을 추가한다.

(1)번과 (4)번에 어떤 재료를 사용하느냐의 차이만 있을 뿐 큰 알고리즘은 같다. 이럴 경우 (1)~(4)를 하나의 알고리즘으로 메소드에 넣고, 차이점이 있는 (2)번과 (4)번만 각각의 서브 클래스에서 처리하도록 한다.

 

예시 코드

커피와 홍차 모두 카페인이 들어있기 때문에 CaffeineBevarage라는 클래스로 만들어보겠다.

템플릿 메소드 패턴의 클래스

// java
// Template Method Pattern
public abstract class CaffeineBeverage {
	final void prepareRecipe() {
    	boilWater();
        brew();
        pourInCup();
        addCondiments();
    }
	abstract void brew();
    abstract void addCondiments();
    void boilWater() {
    	System.out.println("물 끓이는 중");
    }
    void pourInCup() {
    	System.out.println("컵에 따르는 중");
    }
}

커피와 홍차를 만들 때 똑같은 prepareRecipe() 메소드를 사용한다. 서브 클래스에서 이 메소드를 오버라이드해서 아무렇게나 음료를 만들지 못하도록 final로 선언했다. 

// 홍차, 커피
public class Tea extends CaffeinBeverage {
	public void brew() {
    	System.out.println("차를 우려내는 중");
    }
    public void addCondiments() {
		System.out.println("레몬을 추가하는 중");    
    }
}

public class Coffee extends CaffeinBeverage {
	public void brew() {
    	System.out.println("필터로 커피를 우려내는 중");
    }
    public void addCondiments() {
    	System.out.println("설탕과 커피를 추가하는 중");
    }
}

 

두번째와 네번째 단계인 brew와 addCondiments는 추상 메소드로 선언하여 서브 클래스에서 정의하여 사용하도록 했다.

 

구조

추상 클래스는 템플릿 메소드를 포함하고 있고, 그 템플릿 메소드에서 알고리즘의 골격을 정의한다.

알고리즘의 여러 단계 중 일부는 서브 클래스에서 정의하여 사용할 수 있도록 추상화되어있다.

 

 

유의점

템플리 메소드 패턴을 사용할 때 유의할 부분은 추상 메소드가 많아지지 않도록 해야하는 것이다. 왜냐하면 모든 추상 메소드를 서브 클래스에서 채워줘야하기 때문에 갯수가 많을 경우 구현하기 번거로워질 수 있다. 

추상 메소드의 갯수를 줄이기 위해서는 알고리즘의 단계를 너무 잘게 쪼개지 않고 큼지막하게 나누는 것도 방법이 될 수 있다.

 


 

Template Method & Hook 템플릿 메소드와 후크

후크는 수퍼클래스에서 만들어놓은 빈 메소드이다. 필요에 따라 서브클래스에서 오버라이드하여 사용할 수 있다.

 

후크 사용 예시

시럽 추가 유무, 나는 커피에는 바닐라 시럽을 넣어 마시고 홍차는 시럽을 추가하지 않는다. 

따라서 같은 알고리즘으로 음료를 만들고 마지막에 커피에만 시럽을 넣는다.

 

코드

// 후크 메소드 - addSyrup()
public abstract class CaffeineBeverageWithHook {
	void prepareRecipe() {
    	boilWater();
        brew();
        pourInCup();
        addSyrup(); // 후크 메소드
    }
    abstract void brew();
    abstract void addCondiments();
    void boilWater() {
    	System.out.println("물 끓이는 중");
    };
    void pourInCup() {
    	System.out.println("컵에 따르는 중");
	};
    void addSyrup() { 
    	// 빈 메소드
        // 서브 클래스에서 오버라이드하여 사용. 
    };
}

 

커피의 경우 수퍼클래스에서 선언된 addSyrup을 재정의하여 바닐라 시럽을 추가한다.

public class CoffeWithHook extends CaffeinBeverageWithHook {
	public void brew() {
    	...
    };
    public void addCondimnets() {
    	...
    };
    public void addSyrup(){ // 후크를 오버라이드해서 원하는 기능 집어 넣음
    	System.out.println("바닐라 시럽 넣는 중");
	};
}

 

홍차는 위와 동일한 코드에서 addSyrup메소드만 정의하지 않으면 된다. 수퍼 클래스에서 비어있는 메소드이기 때문에 아무것도 처리하지 않는다.

 

장점

이와 같이 후크를 사용할 경우, 서브 클래스 입장에서는 다양한 위치에서 알고리즘에 끼어들 수 있다.

즉, 알고리즘의 특정 부분이 선택적으로만 적용해야할 경우 사용하면 편리하다.

 

 

 

검색 페이지에서

시간 검색, 이벤트 검색, 텍스트 검색 등 여러 검색 페이지가 있는데 

여기서 검색하려는 필터 채널과 날짜와시간은 같이 쓰고 시간, 이벤트,텍스트만 따로 씀

알고리즘은 검색에서 독점하고 있음. 그리고 채널 선택, 날짜와 시간 선택, 검색 버튼, 초기화 버튼은 검색 클래스에서 수행하고,

특수 필터 선택만 하위 서브 클래스에서 실행하도록 하고 있음

 

반응형