일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- github
- 네트워크
- Java
- mybatis
- reactor
- network
- NoSQL
- mongodb
- ajax
- reactive
- nodejs
- redis
- socket
- cache
- git
- javascript
- Heap
- libuv
- 데이터통신
- Linux
- VCS
- Static
- effective
- Lombok
- AWS
- spring
- r
- HTTP
- html
- Elk
- Today
- Total
빨간색코딩
Template Method Pattern (템플릿 메소드 패턴, hook 메소드, 예제) 본문
jdbcTemplate, restTemplate 등 스프링에서 지원하는 많은 템플릿들을 보았다. 이런 것들은 기계적이며 길고 반복적인 코드들을 깔끔하게 처리해준다. (ex. jdbc 코드를 짤때 커넥션부터해서 close까지의 그 긴 코드를 몇 줄만으로도 똑같은 기능을 할 수 있는..) 이런 것들이 바로 템플릿 메소드 패턴이 적용된 좋은 예제들이다.(근데 더 알아보니까 다른 디자인패턴이라는 듯...ㅜ) 가져다 쓰기만 하면 재미없으니 탐구를 해보자ㅋㅋ
1. 템플릿메소드 패턴은 왜 쓰는가?
네이버 이미지에서 따온 사진이다. 이것만큼 템플릿을 잘 설명할 수 없을 것 같다ㅋㅋㅋ 이 템플릿 자를 사용하면 누구나 똑같은 네모세모를 찍어낼 수 있다. 템플릿메소드도 이와 무관하지 않다. 상위 클래스(추상 클래스)에서는 템플릿에 해당하는 메소드들이 정의되어 있고, 하위 클래스에서 이를 상속받아 메소드를 구현하는 것이다. 이렇게하면 연관된 것들끼리 뼈대를 통일할 수 있고, 하위 클래스에서 코드량이 매우 줄어들고 핵심로직만 작성할 수 있다.
2. 사용 예제 먼저보기
아래에는 무선, 로봇 청소기가 있다.
무선청소기 WirelessVacuum.java
public class WirelessVacuum {
private int battery = 0;
public void charge(int count) {
if (battery < 100) {
System.out.println("충전중...");
battery += count;
} else {
System.out.println("충전완료!!");
}
}
public void run() {
System.out.println("전원 ON : 부릉");
System.out.println("모터 시동 : 부릉부릉");
System.out.println("흡입 시작 : 위이이잉");
while (battery > 0) {
System.out.println("슈우우우우욱~~~!");
battery--;
}
}
}
로봇청소기 RoboticVacuum.java
public class RoboticVacuum {
private int battery = 0;
public void charge(int count) {
if (battery < 100) {
System.out.println("충전중...");
battery += count;
} else {
System.out.println("충전완료!!");
}
}
public void run() {
System.out.println("전원 ON : Hello world!");
System.out.println("모터 시동 : 띠용");
System.out.println("흡입 시작 : 조용..");
while (battery > 0) {
System.out.println("센서로 위치파악");
System.out.println("이동!");
System.out.println("조용하게 슉");
battery--;
}
}
}
청소기 사용 유저 VacuumClient.java
public class VacuumClient {
public static void main(String[] args) {
WirelessVacuum cleaner1 = new WirelessVacuum();
RoboticVacuum cleaner2 = new RoboticVacuum();
System.out.println("=== 무선청소기 start ===");
cleaner1.charge(2);
cleaner1.run();
System.out.println("=== 무선청소기 end ===");
System.out.println("=== 로봇청소기 start ===");
cleaner2.charge(2);
cleaner2.run();
System.out.println("=== 로봇청소기 end ===");
}
}
패턴 적용
위의 코드에서 반복코드가 발생하고 있다. 템플릿 메소드 패턴을 적용해보자.
VacuumTemplate.java
public abstract class VacuumTemplate {
private int battery = 0;
// 일반메소드(=Hook 메소드) : 구현해도되고 안해도 되고..
public void charge(int count) {
if (battery < 100) {
System.out.println("충전중...");
battery += count;
} else {
System.out.println("충전완료!!");
}
}
// 템플릿 메소드
public void run() {
prepareRun();
while (battery > 0) {
working();
battery--;
}
}
// 추상메소드 : 하위클래스에서 무조건 구현해야함
abstract void prepareRun();
abstract void working();
}
WirelessVacuum.java
public class WirelessVacuum extends VacuumTemplate {
@Override
void prepareRun() {
System.out.println("전원 ON : 부릉");
System.out.println("모터 시동 : 부릉부릉");
System.out.println("흡입 시작 : 위이이잉");
}
@Override
void working() {
System.out.println("슈우우우우욱~~~!");
}
}
RoboticVacuum.java
public class RoboticVacuum extends VacuumTemplate {
@Override
void prepareRun() {
System.out.println("전원 ON : Hello world!");
System.out.println("모터 시동 : 띠용");
System.out.println("흡입 시작 : 조용..");
}
@Override
void working() {
System.out.println("센서로 위치파악");
System.out.println("이동!");
System.out.println("조용하게 슉");
}
}
살펴보기
VacuumTemplate 를 보면 반복되는 코드를 아주 예쁘게 처리하고, 달라질 수 있는 부분에 한해서만 하위클래스에서 꼭 구현하도록 abstract 키워드를 붙여 추상메소드를 만들어 주었다. 하위 클래스에서는 이 추상메소드만 구현한다면, Client쪽에서 같은 결과를 볼 수 있는 것이다.
- Hook 메소드 : 상황에 맞게 정의하거나 안해도 된다.
- 템플릿 메소드 : 공통적인 로직이 들어가며, 하위클래스마다 달라질 수 있는 부분은 추상메소드를 박아둔다.
예제 출력 결과
=== 무선청소기 start ===
충전중...
전원 ON : 부릉
모터 시동 : 부릉부릉
흡입 시작 : 위이이잉
슈우우우우욱~~~!
슈우우우우욱~~~!
=== 무선청소기 end ===
=== 로봇청소기 start ===
충전중...
전원 ON : Hello world!
모터 시동 : 띠용
흡입 시작 : 조용..
센서로 위치파악
이동!
조용하게 슉
센서로 위치파악
이동!
조용하게 슉
=== 로봇청소기 end ===