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

디자인패턴 2014. 11. 11. 14:26

1. 템플릿 메소드 패턴이란?


 템플릿 메소드 패턴에서는 메소드에서 알고리즘의 골격을 정의한다. 알고리즘의 여러 단계 중 일부는 추상(Abstract) 메소드로 정의하여 subclass에서 특정 알고리즘을 제공할 수 있다.
 템플릿 메소드를 이용하면 알고리즘의 구조는 그대로 유지하면서 subclass에서 알고리즘의 특정 단계를 재정의할 수 있다.



2. 템플릿 메소드 패턴 예시

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// 템플릿 메소드가 들어있는 추상(Abstract) 클래스
public abstract class CaffeineBeverage {
 
 // 템플릿 메소드
 // 카페인이 들어있는 음료를 만들기 위한 알고리즘에 대한 템플릿.
 // Subclass에서 이 메소드를 override해서 아무렇게나 음료를 만들지 못하도록 final로 선언함.
 final void prepareRecipe() {
  boilWater();
  brew();
  pourInCup();
   
  // 손님이 첨가물을 넣어달라고 했을때만, addCondiments()를 호출함.
  if (customerWantsCondiments()) {
   addCondiments();
  }
 }
  
 // 두 메소드는 subclass에서 알아서 처리하게 추상(Abstract) 메소드로 선언함.
 // Subclass에서 알고리즘의 특정 단계를 제공해야만 하는 경우에 사용.
 abstract void brew();
 abstract void addCondiments();
  
 // 물을 끓이고 컵에 물을 따르는 행동은 같으므로 구상(Concrete) 메소드로 구현함.
 void boilWater() {
  System.out.println("물 끓이는 중");
 }
  
 void pourInCup() {
  System.out.println("컵에 따르는 중");
 }
  
 // Hook 메소드
 // Subclass에서 필요에 따라 override할 수 있는 메소드이다.
 // 알고리즘의 특정 부분이 선택적으로 적용되야 하는 경우에 사용함.
 boolean customerWantsCondiments() {
  return true;
 }
}
 
 
 
public class Coffee extends CaffeineBeverage {
 
 @Override
 void brew() {
  System.out.println("필터로 커피를 우려내는 중");
 }
 
 @Override
 void addCondiments() {
  System.out.println("설탕과 커피를 추가하는 중");
 }
  
 public boolean customerWantsCondiments() {
  String answer = getUserInput();
   
  if (answer.toLowerCase().startsWith("y")) {
   return true;
  } else {
   return 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 오류");
  }
   
  if (answer == null) {
   return "no";
  }
   
  return answer;
 }
}
 
 
 
public class Tea extends CaffeineBeverage {
 
 @Override
 void brew() {
  System.out.println("차를 우려내는 중");
 }
 
 @Override
 void addCondiments() {
  System.out.println("레몬을 추가하는 중");
 }
  
 public boolean customerWantsCondiments() {
  String answer = getUserInput();
   
  if (answer.toLowerCase().startsWith("y")) {
   return true;
  } else {
   return 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 오류");
  }
   
  if (answer == null) {
   return "no";
  }
   
  return answer;
 }
}
 
 
public class BeverageTestDrive {
 
 /**
  * @param args
  */
 public static void main(String[] args) {
  Tea tea = new Tea();
  Coffee coffee = new Coffee();
   
  System.out.println("\n차 준비중...");
  tea.prepareRecipe();
   
  System.out.println("\n커피 준비중...");
  coffee.prepareRecipe();
 
 }
 
}





참고
Head FIrst Design Pattern : 스토리가 있는 패턴 학습법
http://www.gurubee.net/pages/viewpage.action?pageId=1507401



출처 - http://digitanomad.blogspot.kr/2013/04/template-method-pattern.html

'디자인패턴' 카테고리의 다른 글

스트래티지 패턴(Strategy Pattern)  (0) 2014.11.11
퍼사드 패턴(Facade Pattern)  (0) 2014.11.11
커맨드 패턴(Command Pattern)  (0) 2014.11.11
싱글턴 패턴(Singleton Pattern)  (0) 2014.11.11
팩토리 패턴(Factory Pattern)  (0) 2014.11.11
: