Template Method
우리는 '템플릿'이라는 것을 많이 사용해왔다. 템플릿은 일정한 틀이나 형식같은 것을 말한다. 일종의 뼈대라고 보면 된다. ppt 템플릿을 사용해 템플릿의 일정한 틀에 맞추어 글만 바꾸어서 ppt를 작성하듯이, 템플릿 메소드는 일정한 뼈대(추상 메소드)에 살만 덧붙여서 구체적인 메소드(하위 메소드)를 얻게 된다.
하위 클래스들의 뼈대가 될 메소드들을 추상 클래스에 정의함으로써 알고리즘의 구조는 변하지 않도록 한다. 공통으로 적용되는 메소드들은 일반 메소드로 구현하고, 하나 이상의 메소드를 추상 메소드로 정의해 서브클래스에서 확장구현한다.
Example
뭐 뼈대고 뭐고 어쩌라는걸까~ 할 수 있으니 쉽게 예를 들어보자.
오늘 집에 친구들이 놀러오기로 했는데, 친구들이 고기를 사온다고 하기에 나는 면요리 두가지를 만들어 주기로 했다. 간장비빔국수와 칼국수를 만들기로 했는데, 이를 소스 코드로 풀어보면 다음과 같다.
xxxxxxxxxx
class SoySauceNoodle {
void prepare() {
System.out.println("물을 끓인다.");
System.out.println("소면을 삶는다.");
System.out.println("간장소스에 버무린다.");
System.out.println("그릇에 담는다.");
}
}
class Kalguksu {
void prepare() {
System.out.println("물을 끓인다.");
System.out.println("칼국수면을 삶는다.");
System.out.println("멸치육수에 면을 넣는다.");
System.out.println("그릇에 담는다.");
}
}
public class MakeNoodle {
public static void main(String[] args) {
SoySauceNoodle noodle1 = new SoySauceNoodle();
Kalguksu noodle2 = new Kalguksu();
noodle1.prepare();
noodle2.prepare();
}
}
xxxxxxxxxx
[실행결과]
물을 끓인다.
소면을 삶는다.
간장소스에 버무린다.
그릇에 담는다.
물을 끓인다.
칼국수면을 삶는다.
멸치육수에 면을 넣는다.
그릇에 담는다.
요리는 무사히 완성되었다! 그런데.. 뭔가 두 요리의 레시피가 비슷한 것 같지 않은가?
간장비빔국수도, 칼국수도, 면의 종류와 소스가 다를 뿐 그 과정은 비슷하게 흘러간다. 이럴 때 템플릿 메소드 패턴을 이용해서 일련의 과정을 추상화할 수 있다.
우선 뼈대를 만들어보자. 요리 과정을 하나의 큰 뼈대로 정리해 줄 추상 클래스를 작성해보면
xxxxxxxxxx
public abstract class Noodle {
final void prepare() {
boilWater();
boilNoodles();
putNoodles();
putInBowls();
}
void boilWater() { System.out.println("물을 끓인다."); }
abstract void boilNoodles();
abstract void putNoodles();
void putInBowls() { System.out.println("그릇에 담는다."); }
}
위와 같이 작성할 수 있겠다.
이 추상 클래스를 상속 받아서 면을 삶을 물을 끓이고, 면을 삶고, 양념 혹은 육수에 면을 넣고, 그릇에 담는 과정 자체는 그대로 두고 어떤 면을 어떤 소스에 넣을 것인지만 변경할 수 있게 되었다.
이제 다시 요리를 해보자.
xxxxxxxxxx
class SoySauceNoodle extends Noodle {
void boilNoodles() {
System.out.println("소면을 삶는다.");
}
void putNoodles() {
System.out.println("간장소스에 버무린다.");
}
}
class Kalguksu extends Noodle {
void boilNoodles() {
System.out.println("칼국수면을 삶는다.");
}
void putNoodles() {
System.out.println("멸치육수에 면을 넣는다.");
}
}
public class MakeNoodle {
public static void main(String[] args) {
SoySauceNoodle noodle1 = new SoySauceNoodle();
Kalguksu noodle2 = new Kalguksu();
noodle1.prepare();
noodle2.prepare();
}
}
xxxxxxxxxx
[실행결과]
물을 끓인다.
소면을 삶는다.
간장소스에 버무린다.
그릇에 담는다.
물을 끓인다.
칼국수면을 삶는다.
멸치육수에 면을 넣는다.
그릇에 담는다.
이렇게 면과 소스만 정함으로써 요리를 더 편하게 완성할 수 있게 되었다.
이와 같이 템플릿 메소드 패턴을 사용하면 전체적인 알고리즘의 흐름은 통일시키면서 메서드를 확장구현할 수 있다. 또한 보기에도 쉽기 때문에 코드 수정도 편리해진다.
추가
후킹메소드를 이용해 코드를 더 유연하게 해줄 수도 있다. 고명을 담고싶을 경우 고명을 담는 과정을 후크처리해두고, 칼국수에는 고명을 담는 과정을 생략하고 비빔국수 위에는 오이와 계란을 얹을 수도 있다.
'공부 > JAVA' 카테고리의 다른 글
[디자인패턴] 싱글톤(Singleton) (0) | 2018.11.19 |
---|---|
[Thread] 동기화와 교착상태 (0) | 2018.06.11 |
[Thread] Thread (0) | 2018.06.11 |
[자료구조] 비선형구조 (0) | 2018.06.08 |
[자료구조] 선형구조 (0) | 2018.06.05 |
댓글