템플릿 메서드 패턴은 여러 클래스에서 공통으로 사용하는 메서드를 상위 클래스에서 정의하고, 하위 클래스마다 다르게 구현해야하는 세부적인 사항을 하위 클래스에서 구현하는 패턴을 말한다.
템플릿메서드의 필요성을 보여주기위한 예로, 아이스 아메리카노와 아이스 라떼 만드는 법을 코드로 구현해보자!
// IceAmericano.java
public class IceAmericano {
public void makeIceAmericano() {
putEspresso();
putIce();
putMilk();
}
private void putEspresso() {
System.out.println("에스프레소를 넣는다.");
}
private void putIce() {
System.out.println("얼음을 넣는다.");
}
private void putWater() {
System.out.println("끓는 물을 넣는다.");
}
}
// IceLatte.java
public class IceLatte {
public void makeIceLatte() {
putEspresso();
putIce();
putMilk();
}
private void putEspresso() {
System.out.println("에스프레소를 넣는다.");
}
private void putIce() {
System.out.println("얼음을 넣는다.");
}
private void putMilk() {
System.out.println("끓는 우유를 넣는다.");
}
}
// MakeCoffee.java
public class MakeCoffee {
public static void main(String args[]){
IceAmericano americano = new IceAmericano();
IceLatte latte = new IceLatte();
americano.makeIceAmericano();
System.out.println("=======");
latte.makeIceLatte();
}
}
하지만 위 결과를 보면, 에스프레소를 넣는것과 얼음을 넣는다는 행위는 중복되고 있다. 중복 방지를 위해 템플릿메서드를 사용하자!
공통으로 작업하는 항목을 Coffee클래스에 정의하고, 상속을 통해 자식클래스에서 자세한 것을 정의하면 된다.
// Coffee.java
public abstract class Coffee {
final void makeCoffee() {
putEspresso();
putIce();
putExtra();
}
private void putEspresso() {
System.out.println("에스프레소를 넣는다.");
}
private void putIce() {
System.out.println("얼음을 넣는다.");
}
// 확장/변화가 필요한 코드이고, 용도에 맞게 상속받아 구현한다.
private void putExtra();
}
// IceAmericano.java
public class IceAmericano extends Coffee {
@Override
private void putExtra() {
System.out.println("끓는 물을 넣는다.");
}
}
// IceLatte.java
public class IceLatte extends Coffee {
@Override
private void putExtra() {
System.out.println("끓는 우유를 넣는다.");
}
}
// Coffee.java
public class Coffee {
public static void main(String args[]){
IceAmericano americano = new IceAmericano();
IceLatte latte = new IceLatte();
americano.makeIceAmericano();
System.out.println("=======");
latte.makeIceLatte();
}
}
템플릿메서드패턴의 특징은 전체적인 레이아웃을 통일하지만, 상속받은 클래스로 하여금 유연성을 주도록 하는 디자인 패턴이다.
추상 메소드와 훅 메소드를 사용해서 전체적인 알고리즘을 유지하되 유연하게 기능을 변경할 때 사용한다.
아이스 아메리카노에 끓는물을 넣다니...!