Writing /volume1/Web/Public/dokuwiki/data/log/deprecated/2024-11-15.log failed
差分
このページの2つのバージョン間の差分を表示します。
両方とも前のリビジョン前のリビジョン次のリビジョン | 前のリビジョン | ||
study:java:design_pattern:template_method [2008/08/16 09:18] – banana | study:java:design_pattern:template_method [2008/09/03 14:27] (現在) – banana | ||
---|---|---|---|
行 15: | 行 15: | ||
클래스 다이어그램을 한번 살펴봅시다. | 클래스 다이어그램을 한번 살펴봅시다. | ||
+ | {{: | ||
+ | |||
+ | {{keywords> | ||
===== snippet of AbstractClass ===== | ===== snippet of AbstractClass ===== | ||
行 36: | 行 39: | ||
void hook() {} | void hook() {} | ||
+ | } | ||
+ | </ | ||
+ | 여기서 구상단계는 추상 클래스내에서 정의됩니다. 이 메소드는 final로 선언되어 있기 때문에 서브 클래스에서 오버라이드 할 수 없겠죠.\\ 이 메소드는 템플릿 메소드에서 직접 호출할 수도 있고, 서브클래스에서 호출해서 사용할 수도 있습니다.\\ | ||
+ | **%%hook()%% | ||
+ | **는 아무것도 하지 않지만, 유연성을 제공하도록 위해 정의 되었습니다. 이런 메소드는 " | ||
+ | 서브클래스에서 오버라이드 할 수 있지만, 반드시 그래야 하는 건 아니죠. 이 메소드를 어떤 식으로 활용하는지는 밑에서 살표보도록 | ||
+ | 하겠습니다. | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ===== template method and hook ===== | ||
+ | 후크는 추상 클래스에서 선언되는 메소드긴 하지만 기본적인 내용만 구현되어 있거나 아무 코드도 들어있지 않은 메소드입니다.\\ | ||
+ | 이렇게 하면 서브클래스 입장에서는 다양한 위치에서 알고리즘에 끼어들 수 있습니다. 물론 그냥 무시하고 넘어갈수도 있죠. | ||
+ | |||
+ | 후크는 다양한 용도로 쓰일 수 있습니다. 일단 한가지 사용법을 살펴볼까요? | ||
+ | |||
+ | <code java> | ||
+ | public abstract class CaffeineBeverageWithHook{ | ||
+ | void prepareRecipe(){ | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | |||
+ | abstract void brew(); | ||
+ | | ||
+ | abstract void addCondiments(); | ||
+ | |||
+ | void boilWater(){ | ||
+ | | ||
+ | } | ||
+ | |||
+ | void pourInCup(){ | ||
+ | | ||
+ | } | ||
+ | |||
+ | boolean customerWantsCondiments(){ | ||
+ | return true; | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | 여기서 후크 역할을 하는 메소드가 **%%customerWantsCondiments()%%**입니다. 이 메소드는 필요에 따라 서브클래스에서 | ||
+ | 오버라이드 할 수 있습니다.\\ | ||
+ | |||
+ | 후크를 사용하려면 서브클래스에서 오버라이드 해야 합니다.\\ 이 예에서는 **%%CaffeineBeverage%%**에서 알고리즘의 특정 부분을 | ||
+ | 처리할지 여부를 결정하기 위한 용도로 후크를 사용했습니다.\\ 음료에 첨가물을 추가할 지 여부를 결정하기 위한 메소드죠. | ||
+ | |||
+ | 손님이 첨가물을 추가하고 싶어하는지 어떻게 알 수 있을까요? | ||
+ | |||
+ | <code java> | ||
+ | public class CoffeeWithBook extends CaffeineBeverageWithHook{ | ||
+ | | ||
+ | System.out.println(" | ||
+ | } | ||
+ | |||
+ | | ||
+ | System.out.println(" | ||
+ | } | ||
+ | |||
+ | | ||
+ | String answer =getUserInput(); | ||
+ | | ||
+ | if(answer.toLowerCase().startsWith(" | ||
+ | return true; | ||
+ | }else{ | ||
+ | return false; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | | ||
+ | | ||
+ | |||
+ | |||
+ | | ||
+ | |||
+ | | ||
+ | |||
+ | try{ | ||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | |||
+ | | ||
+ | | ||
+ | } | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===== sorting using template-method pattern ===== | ||
+ | 배열을 가지고 자주 하는 일 가운데 뭐가 있을까요? | ||
+ | |||
+ | 자바의 Arrays 클래스에는 정렬할 때 쓸 수 있는 편리한 템플릿 메소드가 있습니다. 그 메소드가 어떤 식으로 작동하는지 살펴봅시다. | ||
+ | |||
+ | <code java> | ||
+ | public static void sort(Object[] a){ | ||
+ | Object aux[] = (Object[])a.clone(); | ||
+ | mergeSort(aux, | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | 이 %%sort()%%메소드는 배열의 복사본을 만든 다음 %%mergeSort()%%를 호출할때 대상 배열로 전달해 주기 위한 보조 메소드입니다.\\ %%mergeSort()%%를 호출할 때는 배열의 길이와 첫번째 원소의 위치(0)도 알려줘야 합니다. | ||
+ | |||
+ | <code java> | ||
+ | private static void mergeSort(Object[] src, Object[] dest, int low, int high, int off){ | ||
+ | | ||
+ | for(int j=i; j>low && ((Comparable)dest[j-1]).compareTo((Comparable)dest[j])> | ||
+ | swap(dest, j, j-1); | ||
+ | } | ||
+ | } | ||
+ | | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | %%mergeSort()%%메소드에는 정렬 알고리즘이 들어있으며, | ||
+ | 정렬이 실제로 어떤 식으로 진행되는지 알고 싶다면 썬에서 만든 소스 코드를 확인해 보세요.\\ | ||
+ | %%swap%%메소드는 %%Arrays%% 클래스에 이미 정의되어 있는 구상 메소드입니다. | ||
+ | |||
+ | ===== implementation of Comparable interface ===== | ||
+ | 이제 정렬 알고리즘을 완성하기 위해 **compareTo()**메소드를 구현해보겠습니다. | ||
+ | |||
+ | <code java> | ||
+ | public class Duck implements Comparable{ | ||
+ | | ||
+ | int weight; | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | } | ||
+ | |||
+ | | ||
+ | | ||
+ | } | ||
+ | |||
+ | | ||
+ | |||
+ | Duck otherDuck = (Duck) object; | ||
+ | |||
+ | | ||
+ | return -1; | ||
+ | }else if(this.weight == otherDuck.weight){ | ||
+ | return 0; | ||
+ | | ||
+ | return 1; | ||
+ | } | ||
+ | } | ||
} | } | ||
</ | </ | ||