소프트웨어 설계 단계에서 공통적으로 발생하는 문제에 대한 재사용 가능한 해결 방안을 정형화시킨것
부모 클래스에서 문제 해결 방안(작업 알고리즘)의 구조, 뼈대, 틀을 정의하고 자식 클래스에서 재사용하게 하는 설계 패턴
ex) 피자 생성에 필요한 작업 공정(prepare(), topping(), bake(), cutting(), boxing())의 구조를 makePizza()라는 템플릿메소드를 정의해 하위 클래스에게 물려준다. 또한 topping()은 부모 차원에서 만들어서 물려줄 수 없으므로 abstract method로 처리해 반드시 하위 클래스에서 구현하도록 강제시킨다.
템플릿 메소드 디자인 패턴은 개발 생산성 향상 및 작업 공정의 표준화에 기여한다.
public abstract class PizzaService {
protected void prepare() {
System.out.println("도우를 만들다");
}
protected abstract void topping();
protected void bake() {
System.out.println("굽다");
}
protected void cutting() {
System.out.println("자르다");
}
protected void boxing() {
System.out.println("포장하다");
}
public void makePizza() {
prepare();
topping();
bake();
boxing();
}
}
하위 피자 클래스들은 다른 패키지에서 상속받을 것이기때문에 protect로 선언했다. 위에 설명과 동일하게 다르게 작업할 topping() 메소드만 abstract로 선언해주었다.
토핑은 부모 차원에서 구현해 상속시킬 수 없는 작업이고, 하위 피자 클래스에게 구현을 강제하기위해서이다.
하나 이상의 abstract method가 있기때문에 abstract class로 선언되었다.
2. PizzaService를 상속받는 세가지 종류의 피자 클래스를 각각 생성하였다.
import step5.common.PizzaService;
public class BulGogiPizzaService extends PizzaService{
@Override
protected void topping() {
// TODO Auto-generated method stub
System.out.println("불고기 토핑");
}
}
import step5.common.PizzaService;
public class PotatoPizzaService extends PizzaService{
@Override
protected void topping() {
// TODO Auto-generated method stub
System.out.println("감자 토핑");
}
}
import step5.common.PizzaService;
public class SeaFoodPizzaService extends PizzaService {
@Override
protected void topping() {
// TODO Auto-generated method stub
System.out.println("해산물 토핑");
}
}
각각의 피자 클래스에서 extends로 PizzaService를 상속받았고 부모 클래스인 PizzaService에서 abstract로 선언된 topping() 메소드를 오버라이딩했다. 각 메뉴에 맞게 토핑해준것이다.
import step5.common.PizzaService;
import step5.service.BulGogiPizzaService;
import step5.service.PotatoPizzaService;
import step5.service.SeaFoodPizzaService;
public class TestTemplateMethodDesignPattern {
public static void main(String[] args) {
PizzaService pizza1 = new PotatoPizzaService();
pizza1.makePizza();
System.out.println();
PizzaService pizza2 = new SeaFoodPizzaService();
pizza2.makePizza();
System.out.println();
for(int i=0; i<array.length; i++) {
array[i].makePizza();
System.out.println();
}
}
}
부모 클래스의 데이터 타입을 갖는 참조변수 pizza1, pizza2 객체를 만들고, makePizza() 메소드를 호출해서
public void makePizza() {
prepare();
topping();
bake();
boxing();
}
이 함수가 실행되도록 한것이다.
결론적으로 makePizza() 메소드를 통해 작업 공정 표준화가 이루어진것이라고 볼 수 있다.
도우를 만들다
감자 토핑
굽다
포장하다
도우를 만들다
해산물 토핑
굽다
포장하다
도우를 만들다
불고기 토핑
굽다
포장하다
출력은 이렇게 된다.이렇게 하나의 소통방식으로 다양한 객체들이 각자의 방식으로 동작 -> 다형성이라고 볼 수 있고, 템플릿 메소드 makePizza()의 사용법만 익히면 다양한 피자들을 만들 수 있다.
PizzaService[] array = {
new PotatoPizzaService(),
new SeaFoodPizzaService(),
new BulGogiPizzaService()
};
배열을 통해서도 같은 결과를 출력할 수 있다.