Template Method Pattern μ 리
Template Method Pattern μ 리
μν©
컀νΌμ νμ°¨λ₯Ό λμ΄λ κ³Όμ μ μλΉν μ μ¬νλ€. νμ§λ§, 컀νΌλ μλλ₯Ό μ°λ €λ΄κ³ νμ°¨λ μμ μ°λ €λΈλ€.
λλ¨Έμ§ λ°©μ, βλ¬Όμ λμΈλ€β, βμ»΅μ λ°λ₯Έλ€βλ μΌμΉνλ€. κ·Έλ¦¬κ³ λ¬΄μκ°λ₯Ό μ°λ €λ΄κ³ , ν ν(νμ°¨λ λ λͺ¬, 컀νΌλ μ€ν)μ μΆκ°νλ κ²λ μ μ¬νλ€. μ΄λ° μμΌλ‘ κ°μ λ¨κ³λ₯Ό λ°λ₯΄λ κ°μ²΄κ° μ μμ΄ λ§λ€λ©΄, ν νλ¦Ώ λ©μλ ν¨ν΄μ ν΅ν΄ μ€λ³΅λ μ½λλ₯Ό μ κ±°ν μ μλ€.
Template Method Pattern μ΄λ?
ν νλ¦Ώ λ©μλλ λΆλͺ¨ ν΄λμ€μμ μκ³ λ¦¬μ¦μ λ¨κ³λ₯Ό μ μνλ€. νμ ν΄λμ€λ€μ΄ μκ³ λ¦¬μ¦μ νΉμ λ¨κ³λ€μ μ€λ²λΌμ΄λ(μ¬μ μ)ν μ μλλ‘ νλ νλ λμμΈΒ ν¨ν΄μ΄λ€.
λ‘μ§μ λ¨κ³ λ³λ‘ λλ μΌ νλ μν©μμ μ μ©νλ€.
1
λ¨κ³λ³λ‘ λλ λ‘μ§λ€μ΄ μμΌλ‘ μμ λ κ°λ₯μ±μ΄ μμ κ²½μ° λ ν¨μ¨μ μ΄λ€.
[μΆμ²: https://refactoring.guru/ko/design-patterns]
- ꡬμ ν΄λμ€λ€μ λͺ¨λ λ¨κ³λ€μ μ€λ²λΌμ΄λν μ μμ§λ§, 골격(λ¨κ³)λ₯Ό λνλ΄λ
templateMethod()
ν¨μλ μ€λ²λΌμ΄λ ν μ μλ€. Javaμμλ μμ μ΄ λΆκ°λ₯νκ² final ν€μλλ₯Ό μΆκ°νλ€. - κ° λ¨κ³λ€μ μΈλΆλ λ§κ³ , μμλ€λ§ νμ©ν μ μλλ‘ protectedλ‘ μ μΈνλ€
μμ μ½λ
μ± μμλ μ€λͺ ν 컀νΌμ νμ°¨λ₯Ό μμλ‘ μ€λͺ νλ€. 컀νΌ, νμ°¨ λͺ¨λ μΉ΄νμΈ μλ£λΌλ κ²μμ 곡ν΅μ μ΄ μλ€.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public abstract class CaffeineBeverage {
final void prepareRecipe() {
boilWater();
brew();
pourInCup();
addCondiments();
}
abstract void brew();
abstract void addCondiments();
void boilWater() {
System.out.println("Boiling water");
}
void pourInCup() {
System.out.println("Pouring into cup");
}
}
[μ»€νΌ ν΄λμ€]
1
2
3
4
5
6
7
8
public class Coffee extends CaffeineBeverage {
public void brew() {
System.out.println("Dripping Coffee through filter");
}
public void addCondiments() {
System.out.println("Adding Sugar and Milk");
}
}
[νμ°¨ ν΄λμ€]
1
2
3
4
5
6
7
8
public class Tea extends CaffeineBeverage {
public void brew() {
System.out.println("Steeping the tea");
}
public void addCondiments() {
System.out.println("Adding Lemon");
}
}
Hook(ν )
λ§μ½, Typeλ³λ‘ μ νμ μΌλ‘ λ¨κ³λ₯Ό μνν΄μΌ νλ€λ©΄, μλ₯Ό λ€λ©΄ 컀νΌμΈ κ²½μ° μ΄λ²μ μ°μ λ₯Ό νμμ μΌλ‘ μΆκ°ν΄μΌνλ€κ³ ν΄λ³΄μ. κ·Έλ¬λ©΄ λ§μ½ CaffeineBeverageμ νμ μ΄ CoffeeλΌλ©΄ λ¨κ³λ₯Ό λνλ΄λ λ©μλμ Hookμ λ§λ€μ΄λμΌ νλ€. μλνλ©΄ λ¨κ³λ₯Ό λνλ΄λ λ©μλλ finalλ‘ νμν΄λμ€μμ μ€λ²λΌμ΄λ©ν μ μλ€. κ·Έλ κΈ°μ μ€λ²λΌμ΄λ© κ°λ₯νκ² μ΄μ΄λμΌ νλλ°, κ·Έκ² Hook methodμ΄λ€.
μλμ μ½λλ₯Ό νμΈνλ©΄ prepareRecipe()
μ€λ²λΌμ΄λ©ν μ μμ§λ§, customerWantsCondiments()
μ μΈμ λ μ€λ²λΌμ΄λ©ν μ μλ€. κ·Έλ κΈ°μ λ§μ½, νμ°¨λΌλ©΄ customerWantsCondiments()
λ₯Ό μ€λ²λΌμ΄λ©νμ¬ falseλ₯Ό λ°ννκ² νλ©΄ λ¨κ³λ₯Ό μμ ν μ μλ€.
1
2
3
4
5
6
7
8
9
10
11
12
final void prepareRecipe() {
boilWater();
brew();
pourInCup();
if (customerWantsCondiments()) {
addCondiments();
}
}
...
boolean customerWantsCondiments() {
return true;
}
ν 리μ°λ μμΉ
βμ°λ¦¬νν μ°λ½νμ§ λ§μΈμ, μμμ μ°λ½μ€κ²μβ λΌλ μμΉμΌλ‘ κ³ μμ€μ μμκ° μ μμ€μ μμμκ² ν΄μΌνλ μμΉμ΄λ€. μ¦, μ μμ€μ μμκ° κ³ μμ€μ μμλ₯Ό μ°λ½(νΈμΆ)νμ§ μκ³ κ³ μμ€μ΄ νμν λ μ μμ€μ νΈμΆνλ€.
Template method Pattern λν, μ΄λ₯Ό μ€μνκ³ μλ€. μμ μμ(CaffeineBeverage)λ νμν λ(μ€λ²λΌμ΄λ©)λ§ μ μμ€μ λ©μλλ₯Ό νΈμΆνκ³ , λ°λλ‘ μ μμ€μ μμ μμλ₯Ό νΈμΆνλ μΌμ΄ μλ€.
μ¬κΈ°μ μ μμ€μ μμκ° λ°λμ κ³ μμ€μ μμλ₯Ό νΈμΆνλ©΄ μλλ κ²μ΄ μλλ€. λ€λ§, μν μμ‘΄μ±μ΄ μκΈ°λ μΌμ λ°©μ§ν΄μΌνλ€.
Java νλ μμν¬ μμ
μλ°μ ArrayListμμλ sortν¨μκ° μλ€. sortλ template method ν¨ν΄μ μ¬μ©νκ³ μλ€. ꡬ체μ μΈ λ¨κ³λ₯Ό μ μν΄λκ³ , νμ ν΄λμ€μμ λ¨μ§ λΉκ΅νλ λ²λ§(CompareTo) μ μν΄μ£Όλ©΄ λλ€. μλμ μ½λλ βμλΈ ν΄λμ€μμ νλμ λ¨κ³λ₯Ό μ€λ²λΌμ΄λ©νλ€βλΌλ Template method Pattern μ μμ μ ννκ² λΆν©νμ§ μλλ€. μ¬κΈ°μ ArrayListκ° μλ ComparableλΌλ μΈν°νμ΄μ€λ₯Ό ν΅ν΄ μ°κ²°λμ΄μλ€.
μ± μμλ μλ° κ°λ°μκ°, λ°°μ΄μ μλΈν΄λμ€λ₯Ό λ§λ€ μ μλ€λΌλ μ μ½μ‘°κ±΄μ μν΄ λ€μκ³Ό κ°μ λ°©μμ μ ννμκ±°λΌκ³ νλ€.
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
public class Duck implements Comparable<Duck> {
String name;
int weight;
public Duck(String name, int weight) {
this.name = name;
this.weight = weight;
}
public String toString() {
return name + " weighs " + weight;
}
public int compareTo(Duck otherDuck) {
if (this.weight < otherDuck.weight) {
return -1;
} else if (this.weight == otherDuck.weight) {
return 0;
} else { // this.weight > otherDuck.weight
return 1;
}
}
}
[ν μ€νΈ μ½λ]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static void main(String[] args) {
Duck[] ducks = {
new Duck("Daffy", 8),
new Duck("Dewey", 2),
new Duck("Howard", 7),
new Duck("Louie", 2),
new Duck("Donald", 10),
new Duck("Huey", 2)
};
System.out.println("Before sorting:");
display(ducks);
Arrays.sort(ducks);
System.out.println("\nAfter sorting:");
display(ducks);
}
[κ²°κ³Ό]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Before sorting:
Daffy weighs 8
Dewey weighs 2
Howard weighs 7
Louie weighs 2
Donald weighs 10
Huey weighs 2
After sorting:
Dewey weighs 2
Louie weighs 2
Huey weighs 2
Howard weighs 7
Daffy weighs 8
Donald weighs 10
λ€λ₯Έ ν¨ν΄κ³Ό λΉκ΅
[Factory Method Pattern]
ν©ν 리 λ©μλ ν¨ν΄μ νΉνλ Template Method PatternμΌλ‘ κΈ°λ³Έλ¨κ³μμ κ°μ²΄λ₯Ό μμ±νκ³ λ¦¬ν΄νλ Patternμ΄λ€.
[Strategy Pattern]
μ λ΅ ν¨ν΄μ λͺ¨λ μκ³ λ¦¬μ¦μ΄ λ€ λͺ μλμ΄μλ λ°λ©΄, ν νλ¦Ώ λ©μλ ν¨ν΄μ λ¨κ³κ° λͺ μλμ΄μκ³ μΌλΆ λ¨κ³λ νμ ν΄λμ€μμ μ€λ²λΌμ΄λ©ν μ μλ€.
abstractμ Interfaceμ μ°¨μ΄λ?
- abstract : λΆλͺ¨μ κΈ°λ₯μ μμμμ νμ₯μμΌλκ°κ³ μΆμ λ β μμ(λ¨ νκ°μ ν΄λμ€λ§ μμκ°λ₯)
- interface : ν΄λΉ ν΄λμ€κ° κ°μ§ ν¨μμ κΈ°λ₯μ νμ©νκ³ μΆμ λ β ꡬν(μ¬λ¬ μΈν°νμ΄μ€λ ꡬνκ°λ₯)
Javaμμλ λ€μ€ μμμ΄ μλλ€. μν©μ λ§κ² νμ©νμ!