Java 를 대입해서 설명하면
전체적인 음료를 만드는 어떠한 클래스를 추상으로 선언하고
1,3 과정은 공통적이므로 일반 메서드로 구현한다
그 다음 차이가 나는 2,4 과정은 추상 메서드로 구현하여
각각 A, B 음료를 만드는 케이스의 클래스에서 오버라이드 하게 하는 것

알고리즘의 뼈대는 부모 클래스에서 정의하고
구체적인 단계는 자식 클래스에서 구현하는 패턴
만약 음료 2개를 만드는 과정이 있다고 치자
A 음료
정제수를 넣는다
설탕을 넣는다
향료를 넣는다
과일을 넣는다
완성!
B 음료
정제수를 넣는다
에리스리톨을 넣는다
향료를 넣는다
찻잎을 넣는다
완성!
두 과정은 2, 4번째 과정을 제외하면 흐름이 전체적으로 비슷하다
그럼 이 과정 중 2, 4번째만 각자 구성하게 만들면 되지 않을까? 에서 등장한 패턴
음료를 만드는 큰 과정을 만들자
정제수를 넣는다
감미료를 넣는다 → 설탕, 에리스리톨 중 선택
향료를 넣는다
부가 재료를 추가한다 → 과일, 찻잎 중 선택
여기서 2, 4번째 과정만 각각의 음료를 만드는 루트에 연결해서 뽑아내면 된다
💡
Java 를 대입해서 설명하면
전체적인 음료를 만드는 어떠한 클래스를 추상으로 선언하고
1,3 과정은 공통적이므로 일반 메서드로 구현한다
그 다음 차이가 나는 2,4 과정은 추상 메서드로 구현하여
각각 A, B 음료를 만드는 케이스의 클래스에서 오버라이드 하게 하는 것
자식 클래스에서 선택적으로 메서드를 오버라이딩 하게 하는 것
만약 C 음료를 추가로 만드는 루트를 만들려한다
C에는 샤프란이라는 추가 재료가 들어가는데 이게 가격이 비싼 편이다
샤프란이 너무 비싸다보니 넣는 향료에 향을 더 넣을 것이다
하지만 맛을 유지하기 위해 사용하던 향료를 개선하기 전까진 부가 재료를 넣어야 한다
→ 향료의 개선이 완료되면 부가 재료는 필요가 없는데?
4번 과정을 진행하거나 진행하지 않도록 선택하면 되는 것이다
공장에 레버를 추가해서 추가 재료 과정을 진행하거나 않기로 했다
이 때 이 레버를 Hook 이라고 한다
뭐 작동하거나 않거나가 중요한게 아니라 이 메서드를 오버라이딩 해서
템플릿 메서드의 흐름을 제어 하게 하는 것이 포인트
// 음료를 만드는 과정을 가진 공장
public abstract class makeDrink {
// 전체 템플릿 메서드
public final void prepare() {
fillWater();
addSugar();
addSpices();
if(askEtcIngridientYn) {
addEtcIngridient();
}
}
// 각 세부 메서드들
private void fillWater() {
System.out.println("물을 넣는다");
}
private abstract addSugar();
private void addSpices() {
System.out.println("향료를 넣는다");
}
protected abstract void addEtcIngridient();
// Hook 메서드
protected boolean askEtcIngridientYn() {
return true; // 여하튼 기본 과정은 기타 재료를 넣는다
}
}
// A 음료를 만드는 과정
public class Adrink extends makeDrink {
@Override
protected void addSugar() {
System.out.println("설탕을 넣는다");
}
@Override
protected void addEtcIngridient() {
System.out.println("과일을 넣습니다");
}
}
// B 음료를 만드는 과정
public class Bdrink extends makeDrink {
@Override
protected void addSugar() {
System.out.println("에리에스톨을 넣는다");
}
@Override
protected void addEtcIngridient() {
System.out.println("찻잎을 넣습니다");
}
}
// C 음료를 만드는 과정
public class Cdrink extends makeDrink {
@Override
protected void addSugar() {
System.out.println("설탕을 넣는다");
}
@Override
protected void addEtcIngridient() {
System.out.println("샤프란을 넣습니다");
}
// 이러면 레버를 올리면 진행, 내리면 샤프란을 넣지 않게된다
@Override
protected void askEtcIngridientYn() {
Scanner sc = new Scanner.in()
String leverUporDown = sc.nextLine();
return leverUporDown.equals("up");
}
}