|
| 1 | +--- |
| 2 | +layout: pattern |
| 3 | +title: Template method |
| 4 | +folder: template-method |
| 5 | +permalink: /patterns/template-method/ko |
| 6 | +categories: Behavioral |
| 7 | +language: ko |
| 8 | +tags: |
| 9 | +- Gang of Four |
| 10 | +--- |
| 11 | + |
| 12 | +## 의도 |
| 13 | + |
| 14 | +동작 상의 알고리즘의 뼈대를 정의하고 일부 단계들을 하위 클래스에게 미룹니다. 템플릿 메소드는 알고리즘 구조의 변경없이 하위 클래스들이 알고리즘의 특정 단계들을 재정의할 수 있게 합니다. |
| 15 | + |
| 16 | +## 설명 |
| 17 | + |
| 18 | +실제 예제 |
| 19 | + |
| 20 | +> 일반적으로 물건을 훔치는 절차는 동일합니다. 첫번째 단계로 대상을 고릅니다. 다음 단계로 대상을 어느정도 혼란스럽게 만듭니다. 마지막 단계로 물건을 훔칩니다. 하지만, 이 단계를 실행하는 구체적인 방법에는 여러가지가 있습니다. |
| 21 | +
|
| 22 | +쉽게 말하자면 |
| 23 | + |
| 24 | +> 템플릿 메소드 패턴은 일반적인 단계의 아웃라인을 부모 클래스에 제시합니다. 그리고 구체적인 자식 클래스의 구현으로 디테일한 사항들을 정의합니다. |
| 25 | +
|
| 26 | +Wikipedia에 의하면 |
| 27 | + |
| 28 | +> 객체지향 프로그래밍에서, 템플릿 메소드는 디자인 패턴 책에서 감마를 포함한 책의 저자들이 확인한 행동 디자인 패턴 중 하나입니다. 템플릿 메소드는 보통 추상 수퍼클래스인 수퍼클래스에서의 메소드이며 수많은 high-level 단계들의 관점에서 동작의 뼈대를 정의합니다. 이러한 절차들은 템플릿 메소드와 동일한 클래스의 추가적인 헬퍼 메소드들에 의해 구현됩니다. |
| 29 | +
|
| 30 | +**코드 예제** |
| 31 | + |
| 32 | +먼저 구체적인 구현과 함께 템플릿 방법 클래스를 소개합니다. 하위클래스들이 템플릿 메소드를 재정의하지 않는 것을 확실히 하기위해 템플릿 메소드(예제에서는 메소드명`steal`)는 `final`로 선언해야 합니다. 그렇지 않으면 기본 클래스에 정의된 뼈대는 하위 클래스에서 재정의될 수 있습니다. |
| 33 | + |
| 34 | + |
| 35 | +```java |
| 36 | +@Slf4j |
| 37 | +public abstract class StealingMethod { |
| 38 | + |
| 39 | + protected abstract String pickTarget(); |
| 40 | + |
| 41 | + protected abstract void confuseTarget(String target); |
| 42 | + |
| 43 | + protected abstract void stealTheItem(String target); |
| 44 | + |
| 45 | + public final void steal() { |
| 46 | + var target = pickTarget(); |
| 47 | + LOGGER.info("The target has been chosen as {}.", target); |
| 48 | + confuseTarget(target); |
| 49 | + stealTheItem(target); |
| 50 | + } |
| 51 | +} |
| 52 | + |
| 53 | +@Slf4j |
| 54 | +public class SubtleMethod extends StealingMethod { |
| 55 | + |
| 56 | + @Override |
| 57 | + protected String pickTarget() { |
| 58 | + return "shop keeper"; |
| 59 | + } |
| 60 | + |
| 61 | + @Override |
| 62 | + protected void confuseTarget(String target) { |
| 63 | + LOGGER.info("Approach the {} with tears running and hug him!", target); |
| 64 | + } |
| 65 | + |
| 66 | + @Override |
| 67 | + protected void stealTheItem(String target) { |
| 68 | + LOGGER.info("While in close contact grab the {}'s wallet.", target); |
| 69 | + } |
| 70 | +} |
| 71 | + |
| 72 | +@Slf4j |
| 73 | +public class HitAndRunMethod extends StealingMethod { |
| 74 | + |
| 75 | + @Override |
| 76 | + protected String pickTarget() { |
| 77 | + return "old goblin woman"; |
| 78 | + } |
| 79 | + |
| 80 | + @Override |
| 81 | + protected void confuseTarget(String target) { |
| 82 | + LOGGER.info("Approach the {} from behind.", target); |
| 83 | + } |
| 84 | + |
| 85 | + @Override |
| 86 | + protected void stealTheItem(String target) { |
| 87 | + LOGGER.info("Grab the handbag and run away fast!"); |
| 88 | + } |
| 89 | +} |
| 90 | +``` |
| 91 | + |
| 92 | +템플릿 메소드를 담고 있는 반쪽짜리 도적 클래스입니다. |
| 93 | + |
| 94 | +```java |
| 95 | +public class HalflingThief { |
| 96 | + |
| 97 | + private StealingMethod method; |
| 98 | + |
| 99 | + public HalflingThief(StealingMethod method) { |
| 100 | + this.method = method; |
| 101 | + } |
| 102 | + |
| 103 | + public void steal() { |
| 104 | + method.steal(); |
| 105 | + } |
| 106 | + |
| 107 | + public void changeMethod(StealingMethod method) { |
| 108 | + this.method = method; |
| 109 | + } |
| 110 | +} |
| 111 | +``` |
| 112 | + |
| 113 | +그리고 마지막으로, 반쪽짜리 도둑이 다른 도둑질 방법을 어떻게 활용하는지 보여줍니다. |
| 114 | + |
| 115 | +```java |
| 116 | + var thief = new HalflingThief(new HitAndRunMethod()); |
| 117 | + thief.steal(); |
| 118 | + thief.changeMethod(new SubtleMethod()); |
| 119 | + thief.steal(); |
| 120 | +``` |
| 121 | + |
| 122 | +## 클래스 다이어그램 |
| 123 | + |
| 124 | + |
| 125 | + |
| 126 | +## 적용 가능성 |
| 127 | + |
| 128 | +템플릿 메소드는 사용되어야합니다. |
| 129 | + |
| 130 | +* 알고리즘의 변하지않는 부분을 한번만 구현하고, 다양할 수 있는 행위의 구현을 서브클래스에게 맡기기 위해 |
| 131 | +* 중복되는 코드를 피하기위해 서브클래스들 사이의 공통적인 행위를 공통 클래스에서 고려하고 현지화해야 하는 경우. 이것은 Opdyke 와 Johonson이 묘사한 "일반화하기 위한 수정"의 좋은 예입니다. 먼저 기존 코드들 간의 차이를 확인한 다음 새로운 동작으로 구분합니다. 마지막으로, 다른 코드들을 새로운 동작중 하나를 호출하는 템플릿 메소드로 대체합니다. |
| 132 | +* 서브클래스들의 확장을 컨트롤하기 위해. 특정 지점에서 "훅" 작업을 호출하여 해당 지점에서만 확장을 허용하는 템플릿 메서드를 정의할 수 있습니다. |
| 133 | + |
| 134 | +## 튜토리얼 |
| 135 | + |
| 136 | +* [Template-method Pattern Tutorial](https://www.journaldev.com/1763/template-method-design-pattern-in-java) |
| 137 | + |
| 138 | +## 실제 사례 |
| 139 | + |
| 140 | +* [javax.servlet.GenericServlet.init](https://jakarta.ee/specifications/servlet/4.0/apidocs/javax/servlet/GenericServlet.html#init--): |
| 141 | + Method `GenericServlet.init(ServletConfig config)` calls the parameterless method `GenericServlet.init()` which is intended to be overridden in subclasses. |
| 142 | + Method `GenericServlet.init(ServletConfig config)` is the template method in this example. |
| 143 | + |
| 144 | +## 크레딧 |
| 145 | + |
| 146 | +* [Design Patterns: Elements of Reusable Object-Oriented Software](https://www.amazon.com/gp/product/0201633612/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0201633612&linkCode=as2&tag=javadesignpat-20&linkId=675d49790ce11db99d90bde47f1aeb59) |
| 147 | +* [Head First Design Patterns: A Brain-Friendly Guide](https://www.amazon.com/gp/product/0596007124/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0596007124&linkCode=as2&tag=javadesignpat-20&linkId=6b8b6eea86021af6c8e3cd3fc382cb5b) |
| 148 | +* [Refactoring to Patterns](https://www.amazon.com/gp/product/0321213351/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0321213351&linkCode=as2&tag=javadesignpat-20&linkId=2a76fcb387234bc71b1c61150b3cc3a7) |
0 commit comments