본문 바로가기

Coding Note

[Design pattern] Template method

Template method pattern : 일련의 행동을 체계화 할 때 행동 하나하나에 대한 세부 구현은 목적에 따라 바뀔 수 있는 부분이다. 이런 상황에서 세세한 목적에 따라 서로다른 클래스가 생겨난다면 관리의 차원에서 상당히 문제가 된다. Template method는 'template'이라는 단어가 설명하듯, 뼈대를 제공해주므로서 목적에 따른 세세한 변화를 통일성있게 처리할 수 있다.

 

여기서 Template는 template<Type>으로 표현하는 template과는 전혀 관계없으며, 단지 '틀'이라는 의미로 사용될 뿐이다. 이 패턴은 비슷한 목적을 위한 알고리즘에 대해 뼈대가 되는 행동들을 정의하고 이들 행동으로 큰 틀을 '함수'로서 제공하는 역할을 한다. 파생된 클래스는 뼈대는 건들지 않고 세부적인 행동만을 구현함으로써 알고리즘의 실체를 완성하게된다.

 

 

뼈대 클래스(스켈레톤 클래스)는 추상클래스로 알고리즘에 필요한 행동들을 정의하고, templateMethod()에서 이들을 사용하여 알고리즘의 뼈대를 만든다. 이 함수는 final이고 알고리즘의 틀을 정의하는 메소드라 하여 Template method pattern이라 이름붙여진 것이다.

 

이렇게 제공된 틀은 ConcreteClass에서 행동을 구현하여 온전한 알고리즘으로 완성된다. 여기에 주목할 만한 부분은, needOpC()라 표현한 훜 메소드(Hook method)이다. 뼈대가 세워진 후에는 구현 클래스로부터 뼈대의 변경이 불가능하므로 자칫 알고리즘의 1추상클래스-1구현클래스 라는 비효율적인 구조를 가질 수 있다. 이러한 상황을 막기위해 override 가능한 훅 함수를 두어 알고리즘에 유연성을 더하여 준다.

 

이런식의 뼈대 구조는 Builder pattern과는 다른 양상을 보인다. Builder는 조합된 인스턴스의 생성루틴이 추상메소드로 제공되어 파생되는 클래스에서 그 구조를 결정하게 된다. 반면 Template method pattern은 미리 정해져 있는 뼈대로부터 세부 구현만이 변경가능하기 때문에 추상클래스로부터 유사한 형태의 결과를 쉽게 예상할 수 있다.

 

하지만 기반클래스는 요구사항에 따라 언제나 무너질 가능성을 품고있다는 점에서, Template method pattern의 적용은 조심히 이루어 져야 한다. 고려하지 못한 변화에 대처하려다 보면 뼈대가 완전히 바뀌어버릴수도 있는것이다.

 

이 패턴은 '레시피'혹은 '공정' 이라 나타낼 수 있는 알고리즘의 구현에 적용하면 좋다. 예를들어 빵을 만드는 레시피라면

 

1. 밀가루에 물을 넣고 반죽한다.

2. 반죽을 숙성시킨다

3. 버터를 바른다

4. 굽는다

 

와 같이 나타낼 수 있을것이다. 이를 뼈대로 Baking 스켈레톤 클래스를 만들고, 빵의 종류에 따라 각 과정을 세세하게 구현할 수 있다.

 

public abstract class Baker{

public final Bread bakeBread(){

Ingredient ingredients = putFlour();

ingredients.add( putWater() );

dough( ingredients );

if( needFilling() ){

ingredients.add( putFilling() );

}

ingredients.add( putButter() );

return bake( result );

}

 

public abstract Ingredient putFlour();

public abstract Ingredient putWater();

public abstract void dough(Ingredient ingredient);

public abstract Ingredient putFilling();

public abstract Ingredient putButter();

public abstract Bread bake(Ingredient ingredient);

public boolean needFilling(){ return true; }

}

 

public class BaguetteBaker extends Baker{

public Ingredient putFlour(){ return new Flout(); }

 

public Ingredient putWater(){ return new Water(); }

 

public void dough(Ingredient ingredient){

ingredient.dough(3.0f); //3분간 반죽

}

 

public Ingredient putFilling(){ return null; }

 

public Ingredient putButter(){ return new Butter(); }

 

public Bread bake(Ingredient ingredient){

return ingredient.bake(10.0f); //10분간 굽기

}

 

@Override

public boolean needFilling(){ return false; } //속재료는 없음

}

 

눈에 보이듯, 획기적인 방법으로 빵을 반죽안하고 굽게되었다면, 뼈대가 타격을 받는 상황에 봉착한다. 하지만 큰 그림으로 알고리즘을 표현하기 때문에 코드의 가독성과 확장성에서는 뛰어난 효과를 볼 수 있다.

 

한줄요약 : 뛰어난 작품을 만들기 전에는 큰 밑그림을 그리기 마련이다.

'Coding Note' 카테고리의 다른 글

[Design pattern] 디자인 패턴이란  (6) 2013.03.28
[Design pattern] Visitor  (0) 2013.03.27
[Design pattern] Memento  (0) 2013.03.26
[Design pattern] Mediator  (0) 2013.03.25
[Design pattern] Interpreter  (0) 2013.03.18