템플릿 메서드
를 제공한다.public interface Cleaning {
void clean(boolean isRoomDirty);
}
public abstract class Cleaner implements Cleaning {
//템플릿 메서드 (= hook)
@Override
public void clean(boolean isRoomDirty) {
turnOn();
information(); // 추상 메서드 -> 다형성
if (isRoomDirty) {
System.out.println("청소를 시작합니다.");
}
turnOff();
}
private void turnOn() {
System.out.println("전원이 켜집니다.");
}
private void turnOff() {
System.out.println("전원이 꺼집니다.");
}
protected abstract void information();
}
information()
메서드를 구현하여 템플릿 메서드를 완성시켜보자. information()
메서드를 재정의해서 구현체마다 다른 훅의 결과를 볼 수 있다.public class RobotCleaner extends Cleaner {
private String name;
private int power;
private int battery;
public RobotCleaner(final String name, final int power, final int battery) {
this.name = name;
this.power = power;
this.battery = battery;
}
@Override
protected void information() {
System.out.println("I am Robot Cleaner");
System.out.println(String.format("이름 : %s, 파워 : %d,
배터리 : %d%%", name, power, battery));
}
}
public class Cleaner implements Cleaning {
private RobotCleaner cleaner;
public Cleaner(RobotCleaner cleaner) {
this.cleaner = cleaner;
}
//템플릿 메서드 (= hook)
@Override
public void clean(boolean isRoomDirty) {
turnOn();
cleaner.information();
if (isRoomDirty) {
System.out.println("청소를 시작합니다.");
}
turnOff();
}
private void turnOn() {
System.out.println("전원이 켜집니다.");
}
private void turnOff() {
System.out.println("전원이 꺼집니다.");
}
}
단일 책임 원칙(SRP)
을 따르고 있다.개방 폐쇄 원칙(OCP)
역시 잘 지켜지고 있다.리스코프 치환 원칙(LSP)
도 잘 따르고 있다.인터페이스 분리 원칙(ISP)
도 잘 지켜지고 있다.의존성 역전 원칙(DIP)
도 따르게 된다.템플릿 메서드 패턴은 동일한 절차가 반복되는 구조를 가지고 있고, 일부 과정만 다른 로직으로 대체하고 싶을 때 사용할 수 있는 패턴이다. 흐름을 가지고 있는 뼈대(훅)메서드는 상위 클래스에 정의가 되고, 상위 클래스에서 하위 클래스의 메서드를 호출한다는게 특징이다.
전략 패턴과 함께 사용한다면 합성(Composition)의 장점도 함께 누릴 수 있다. 다만 구현이 좀 더 복잡해지는 단점이 있을 것이다. 템플릿 메서드 패턴 역시 쉬우면서도 개발할 때 종종 사용되는 패턴이니 잘 알아두면 유용한 패턴이라고 생각한다.