suyeonme

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

프로그래밍👩🏻‍💻/디자인 패턴

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

suyeonme 2022. 8. 7. 12:39
헤드 퍼스트 디자인 패턴을 읽고 정리한 내용입니다.

템플릿 메소드 패턴(Template Method Pattern)이란?


이미지출처: https://miro.medium.com/max/1382/1*ayWiwk1YjAlLUYzN9fleqw.png

템플릿 메소드 패턴은 즉 일련의 단계로 알고리즘을 정의한 메소드이다. 여러 단계중 하나 이상의 단계가 추상 메소드로 정의되며 그 추상 메소드는 서브 클래스에서 구현한다.

 

템플릿 메소드 패턴 구현


구현 순서

  1. prepareRecipe()는 어떤 알고리즘의 템플릿 역할을 한다.  템플릿 메소드는 서브 클래스에서 오버라이드하지 못하도록 final로 선언한다.
  2. 템플릿 메소드의 일부 알고리즘(추상 메소드)은 서브 클래스에서 구현한다.
public abstract CaffeineBeverage {
  final void prepareRecipe() {
    // 템플릿 메소드
    boilWater();
    brew();
    pourInCup();
    addCondiments();
  }
  
  abstract void brew();
  
  abstract void addCondiments();
  
  void boilWater() {
    //...
  }
  
  void pourInCup() {
    //...
  }
}

서브 클래스

public class Tea extends CaffeineBeverage {
  public void brew() {
    System.out.println("찻잎을 우려내는 중");
  }
  
  public void addCondiments() {
    System.out.println("레몬을 추가하는 중");
  }
}

public class Coffee extends CaffeineBeverage {
  public void brew() {
    System.out.println("커피를 우려내는 중");
  }
  
  public void addCondiments() {
    System.out.println("우유를 추가하는 중");
  }
}

후크(Hook)란?


  • 추상 클래스에서 선언되지만 기본적인 내용만 구현되어있거나 아무 코드도 들어있지 않은 메소드이다.
  • 서브 클래스는 후크를 사용하며 다양한 위치에서 알고리즘에 끼어들 수 있다. 

후크 예시 

추상 클래스

public abstract CaffeineBeverage {
  final void prepareRecipe() {
    boilWater();
    brew();
    pourInCup();
    if(customerWantsCondiments) { // hook!
      addCondiments();
    }
  }
  
  abstract void brew();
  
  abstract void addCondiments();
  
  void boilWater() {
    //...
  }
  
  void pourInCup() {
    //...
  }
  
  boolean customerWantsCondiments() {
    return true;
  }
}

서브 클래스

public class Tea extends CaffeineBeverage {
  public void brew() {
    System.out.println("찻잎을 우려내는 중");
  }
  
  public void addCondiments() {
    System.out.println("레몬을 추가하는 중");
  }
  
  public boolean customerWantsCondiments() {
    String answer = getUserInput();
    return answer.toLowerCase().startsWith("y") ? true : false;
  }
  
  private String getUserInput() {
    String answer = null;
    System.out.print("커피에 설탕과 우유를 넣을까요? (y/n)");
    BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    
    try {
      answer = in.readLine();
    } catch(IOException ioe) {
      System.err.println("IO ERROR");
    }
    if(answer == null) {
      return "no";
    }
    return answer;
  }
}

 

Comments