
템플릿 메소드 패턴은 전체적으로는 동일하면서 부분적으로는 다른 구문으로 구성된 메서드의 코드 중복을 최소화할 때 유용하다.
동일한 기능을 상위 클래스에서 정의하면서 확장, 변화가 필요한 부분만 서브 클래스에서 구현할 수 있도록 한다.

// DocDataMiner
rawData = extractDocData(file)
data = parseDocData(rawData)
// CSVDataMiner
rawData = extractCSVData(file)
data = parseCSVData(rawData)
// PDFDataMiner
rawData = extractPDFData(file)
data = parsePDFData(rawData)
위 세 클래스에는 유사한 코드가 많다.
다양한 데이터 형식을 처리하는 코드는 클래스마다 다르지만 데이터 처리 및 분석을 위한 코드는 거의 같다.
알고리즘은 그대로 두고, 코드 중복을 제거하는 방법이 필요하다.
세 가지 변환 알고리즘을 일련의 단계로 나누고, 이를 메서드로 변환한다.
그리고 단일 템플릿 메서드 내부에서 위에서 변환한 메서드들을 호출한다.
다양한 변환 알고리즘을 사용하기 위해 변환 메소드는 추상화한다.

class DataMiner {
public void mine(Path path) { // 템플릿 메소드
file = openFile(path)
rawData = extractData(file)
data = parseData(rawData) // 이 메소드를 하위 클래스에서 재정의함
analysis = analyzeData(data)
sendReport(analysis)
closeFile(file)
}
protected abstract Data parseData(Data data); // 자식 클래스에서 구현 강제화
}
class PDFDataMiner extends DataMiner {
protected Data parseData(Data data) {
rawData = extractPDFData(file)
data = parsePDFData(rawData)
return data;
}
}
class CSVDataMiner extends DataMiner {
protected Data parseData(Data data) {
rawData = extractCSVData(file)
data = parseCSVData(rawData)
return data;
}
}
위 예제처럼 DataMiner 클래스의 mine 메소드는 PDFDataMiner, CSVDataMiner에서 동일한 기능을 구현한다.
각 자식 클래스에서 구체적으로 정의가 필요한 부분, 즉 parseData 메소드 부분만 각 하위 클래스에서 오버라이드 되도록 한다.
이러한 경우 mine 메소드를 템플릿 메소드라고 부른다.
오버라이드할 필요가 있는 parseData는 primitive 또는 hook 메소드라 부른다.
템플릿 메소드 패턴
템플릿 콜백 패턴
보통 다음과 같이 HttpServlet을 상속 받아서 doGet, doPost를 재정의한다.
public class MyHello extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doGet(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
doGet, doPost는 다음과 같이 HttpServlet 안에 service 템플릿 메소드 안에서 호출한다.

RestTemplate을 이용할때 exchange를 이용해 요청을 보낸다.
// RestTemplate
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
headers.set("X-COM-PERSIST", "NO");
headers.set("X-COM-LOCATION", "USA");
HttpEntity<String> entity = new HttpEntity<String>(headers);
ResponseEntity<String> responseEntity = restTemplate
.exchange("http://localhost:8080/users", HttpMethod.GET, entity, String.class);
다음과 같이 doExceute 템플릿 메소드에서 재정의한 execute를 사용한다.
