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

Template Method Pattern

 


정의


상위 class에서 처리의 흐름을 제어하고, 하위class에서 처리의 내용을 구체화 한다


여러 class에서 공통되는 사항은 상위 추상 class에서 구현하고, 각각의 세부내용은 하위 class에서 구현한다


그 결과 코드의 중복을 줄이고, Refactoring에 유리한 패턴으로 상속을 통한 확장 개발 방법으로 Strategy Pattern과 함께 많이 사용되는 pattern이다.


 

Hook method


필수적이지 않은 부분으로 필요에 따라 선택적으로 sub-class에서 구현할 경우 사용한다


Abstract class에서 정의된 어떠한 행도 하지 않을 수 있고, sub-class의 공통된 동작을 할 수도 있다


또한, sub-class에서 hook method를 재정의 하여 사용하는 방법도 있다


Sub-class에 따라 algorithm에 원하는 내용을 추가할 수 있도록 하는 것이 hook-method의 존재 이유다.


 

요구사항


1.    멤버 함수들의 접근 범위 지정을 명확히 한다.


2.    가상함수, 일반함수로 선언 하는 것 에 대한 기준이 필요


3.    Virtual 함수의 수를 최소화한다.



l  Hollywood Principle

Sub-classupper-class에 구성요소로써 활용될 수 있지만, sub-class upper-class를 호출하여 자신을 호출하게 하면 안된다는 것이다


Template Method Pattern에서도 이러한 원칙을 따르고 있는데


설명을 더하면, abstract class에서는 sub-class에 있는 기능을 호출할 수 있지만


sub-class에서는 abstract-class template method를 호출하거나 수정할 수 없다는 것이다.

 


장점


상위위 class template method에서 알고리즘이 기술되어 있으므로,


하위 class에서는 알고리즘을 일일이 기술할 필요가 없다.


 

소스코드


상위클래스

public abstract class CaffeineBeverageWithHook {

         void prepareRecipe(){

                 boilWater();

                 brew();

                 pourInCup();

                 if(customerWantsCondiments()){

                          addCondiments();

                 }

         }

 

         abstract void brew();

         abstract void addCondiments();

 

         void boilWater(){

                 System.out.println("Boiling water");

         }

 

         void pourInCup(){

                 System.out.println("Pouring into cup");

         }

 

         boolean customerWantsCondiments(){

                 return true;

         }

}

 

하위클래스(coffee)

public class CoffeeWithHook extends CaffeineBeverageWithHook{
         @Override
         void brew() {
                 // TODO Auto-generated method stub
                 System.out.println("Dripping Coffee through filter");
         }
 
         @Override
         void addCondiments() {
                 // TODO Auto-generated method stub
                 System.out.println("Adding Sugar and Milk");
         }
         @Override
         public boolean customerWantsCondiments() {
                 // TODO Auto-generated method stub
                 String answer = getUserInput();
 
                 if(answer.toLowerCase().startsWith("y")){
                          return true;
                 }else{
                          return false;
                 }
         }
 
         private String getUserInput(){
                 String answer = null;
 
                 System.out.println("would you like milk&sugar with your coffee (y/n) ?");
                 BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
 
                 try {
                          answer = in.readLine();
                 } catch (Exception e) {
                          // TODO: handle exception1
                          System.err.println("IO error trying to read your answer");
                 }
 
                 if(answer==null){
                          return "no";
                 }
                 return answer;
         }
}

 

하위클래스(tea)

public class TeaWithHook extends CaffeineBeverageWithHook{
 
         @Override
         void brew() {
                 // TODO Auto-generated method stub
                 System.out.println("Steeping the tea");
         }
 
         @Override
         void addCondiments() {
                 // TODO Auto-generated method stub
                 System.out.println("Adding Lemon");
         }
         @Override
         public boolean customerWantsCondiments() {
                 // TODO Auto-generated method stub
                 String answer = getUserInput();
 
                 if(answer.toLowerCase().startsWith("y")){
                          return true;
                 }else{
                          return false;
                 }
         }
 
         private String getUserInput(){
                 String answer = null;
 
                 System.out.println("would you like lemon with your tea (y/n) ?");
                 BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
 
                 try {
                          answer = in.readLine();
                 } catch (Exception e) {
                          // TODO: handle exception1
                          System.err.println("IO error trying to read your answer");
                 }
 
                 if(answer==null){
                          return "no";
                 }
                 return answer;
         }
 
}

 

Main

public class BeverageTestDrive {
         public static void main(String[] args) {
                 TeaWithHook teaWithHook = new TeaWithHook();
                 CoffeeWithHook coffeeWithHook = new CoffeeWithHook();
                 
                 System.out.println("\n Making tea");
                 teaWithHook.prepareRecipe();
                 
                 System.out.println("\nMaking coffee");
                 coffeeWithHook.prepareRecipe();
         }
}

 

 

결과

Making tea

Boiling water

Steeping the tea

Pouring into cup

would you like lemon with your tea (y/n) ?

y

Adding Lemon

 

Making coffee

Boiling water

Dripping Coffee through filter

Pouring into cup

would you like milk &sugar with your coffee (y/n) ?

y

Adding Sugar and Milk



UML


'SW > DesignPattern' 카테고리의 다른 글

Composite Pattern (컴포지트 패턴)  (0) 2017.09.15
Iterator Pattern (반복자 패턴)  (0) 2017.09.14
Facade Pattern (퍼사드 패턴)  (0) 2017.09.07
Adapter Pattern (어댑터 패턴)  (0) 2017.09.07
Command Pattern (커맨드 패턴)  (0) 2017.09.07