행동 (2) - 템플릿 메소드(Template Method) 패턴
- 추상 클래스로 템플릿을 제공하고 서브 클래스에서 구체적으로 구현하는 패턴
- 즉, 특정 작업을 처리하는 부분을 서브 클래스로 캡슐화하여 수행하도록 설정
- 전체적인 흐름은 동일하면서 부분적으로 코드가 다른 경우 사용하면 코드 중복을 최소화 할 수 있다
- Abstract Class : 템플릿을 제공하는 추상클래스
- Concrete Class : 특정 작업을 처리하는 서브클래스
구현
- Abstract Class
- Hook(후크) : 추상 클래스에 선언되지만 기본적인 내용만 구현되어 있거나 아무것도 들어 있지 않은 메서드
- 후크를 하위 클래스에서 오버라이드 할 수도 있고 그냥 넘어갈 수도 있다
- 상황에 따라 알고리즘의 진행을 변경할 수 있다
public abstract class Teacher {
public final void work() { // 템플릿 메서드
inside();
attendance();
teach();
if (!hasNextClass()) {
outside();
}
}
// 서브 클래스에서 확장이 필요한 부분
public abstract void teach();
// 공통 메서드
private void inside() {
System.out.println("선생님이 강의실로 들어옵니다.");
}
private void attendance() {
System.out.println("선생님이 출석을 부릅니다.");
}
private void outside() {
System.out.println("선생님이 강의실을 나갑니다.");
}
public boolean hasNextClass() { // Hook
return false;
}
}
- Concrete Class
class KoreanTeacher extends Teacher {
@Override
public void teach() {
System.out.println("선생님이 국어를 수업합니다.");
}
@Override
public boolean hasNextClass() {
return true;
}
}
class MathTeacher extends Teacher {
@Override
public void teach() {
System.out.println("선생님이 수학을 수업합니다.");
}
@Override
public boolean hasNextClass() {
return true;
}
}
class EnglishTeacher extends Teacher {
@Override
public void teach() {
System.out.println("선생님이 영어를 수업합니다.");
}
}
- Main
public class Main {
public static void main(String args[]){
Teacher kr = new KoreanTeacher();
Teacher mt = new MathTeacher();
Teacher en = new EnglishTeacher();
kr.work();
mt.work();
en.work();
}
}
익명 내부클래스 사용
- 클래스가 계속 늘어나는 것을 막기 위해 익명 내부클래스를 사용할 수도 있다
public class Main {
public static void main(String args[]){
Teacher teacher = new Teacher() {
@Override
public void teach() {
System.out.println("선생님이 수업합니다.");
}
};
teacher.work();
}
}
장점
- 중복 코드를 줄일 수 있다
- 템플릿 코드를 변경하지 않고 상속받아 특정부분만 변경할 수 있다
단점
- LSP를 위배할 수도 있다
- 자식클래스는 부모클래스의 기능을 전혀 사용하고 있지 않다
- 상속을 통해 부모클래스를 의존하고 있다
- 부모클래스에 변경이 일어나면 자식클래스에도 영향을 미친다
- 알고리즘 구조가 복잡할 수록 템플릿을 유지하기 어려워진다
- 템플릿 메소드보다 전략패턴을 선택하면 1, 2번을 해결할 수 있다
예시
- 정렬이 필요한 곳에
Comparable
를 implement하여compareTo()
구현
템플릿 메서드 VS 전략
- 템플릿 메서드
- 알고리즘의 개요를 정의하고(템플릿) 일부 처리를 하위 클래스에게 넘겨 불완전한 알고리즘을 보충구현한다
- 전략
- 사용하는 클래스의 알고리즘을 완전히 구현한다