템플릿 메서드는 부모 클래스에서 알고리즘 골격을 정의하지만, 해당 알고리즘 구조를 변경하지 않고 자식 클래스들이 알고리즘 특정 단계들을 오버라이딩할 수 있도록 하는 디자인 패턴이다.
public class Dog{
public void playWithOwner(){
System.out.println("귀염둥이 이리온!");
System.out.println("멍! 멍!");
System.out.println("꼬리 살랑 살랑~");
System.out.println("잘했어!");
}
}
public class Cat{
public void playWithOwner(){
System.out.println("귀염둥이 이리온!");
System.out.println("야옹 야옹~");
System.out.println("꼬리 살랑 살랑~");
System.out.println("잘했어!");
}
}
Dog
와 Cat
클래스는 System.out.println("야옹 야옹~");
, System.out.println("멍! 멍!");
코드를 제외하고 모두 중복된 코드이다. 따라서 상속을 사용해 중복 코드는 상위 클래스로 분할하겠다.
public abstract class Animal {
// 템플릿 메서드
public void playWithOnwer(){
System.out.println("귀염둥이 이리온!");
play();
runSomething();
System.out.println("잘했어!");
}
// 추상 메서드
abstract void play();
// Hook(갈고리) 메서드
void runSomething(){
System.out.println("꼬리 살랑 살랑~");
}
}
상위 클래스인 Animal
은 템플릿을 제공하는 playWithOwner()
메서드와 하위 클래스에게 구현을 강제하는 play()
추상 메서드, 하위 클래스가 선택적으로 오버라이딩할 수 있는 runSomething
메서드가 있다.
템플릿 메서드 패턴은 Animal
클래스 처럼 공통 로직을 수행하는 템플릿 메서드와 하위 클래스에 오버라이딩을 강제하는 추상 메서드 또는 선택적으로 오버라이딩할 수 있는 Hook 메서드가 필요하다.
public class Dog extends Animal{
// 추상 메서드 오버라이딩
@Override
void play() {
System.out.println("멍! 멍!");
}
// Hook(갈고리) 메서드 오버라이딩
@Override
void runSomething() {
System.out.println("멍! 멍!~ 꼬리 살랑 살랑~");
}
}
public class Cat extends Animal{
@Override
// 추상 메서드 오버라이딩
void play(){
System.out.println("야옹~ 야옹~");
}
@Override
// Hook(갈고리) 메서드 오버라이딩
void runSomething(){
System.out.println("야옹~ 야옹~ 꼬리 살랑 살랑~");
}
}
public class Driver {
public static void main(String[] args) {
Animal bolt = new Dog();
Animal kitty = new Cat();
bolt.playWithOnwer();
System.out.println();
System.out.println();
kitty.playWithOnwer();
}
}
귀염둥이 이리온!
멍! 멍!
멍! 멍!~ 꼬리 살랑 살랑~
잘했어!
귀염둥이 이리온!
야옹~ 야옹~
야옹~ 야옹~ 꼬리 살랑 살랑~
잘했어!
템플릿 메서드 패턴은 클라이언트들이 알고리즘 특정 단계들만 확장할 수 있도록 하고 싶으나 전체 알고리즘이나 알고리즘 구조는 확장하지 못하도록 하려고 할 때 사용한다.
템플릿 메서드는 모놀리식 알고리즘을 일련의 개별 단계들로 전환할 수 있다. 이 알고리즘은 부모 클래스에서 정의된 구조를 그대로 유지하면서 자식 클래스들에 의해 쉽게 확장될 수 있다.
이 패턴은 약간 차이가 있지만 거의 같은 알고리즘들을 포함하는 여러 클래스가 있는 경우에 사용해야 한다.
같은 알고리즘을 템플릿 메서드로 전환하면 유사한 구현들이 있는 단계들을 상위 클래스로 올릴 수 있으며 코드 중복을 제거할 수 있다. 자식 클래스 중 코드가 다른 부분들은 그대로 남겨놓으면 된다.
✔️ 클라이언트들이 대규모 알고리즘 특정 부분만 오버라이드하도록 해 알고리즘의 다른 부분에 발생하는 변경에 영향을 덜 받도록 할 수 있다.
✔️ 중복 코드를 상위 클래스로 가져올 수 있다.
❌ 하위 클래스로 디폴트 단계 구현을 억제해 리스코프 치환 원칙을 위반할 수도 있다.
❌ 템플릿 메서드들은 단계들이 더 많을수록 유지가 어려운 경향이 있다.
디자인 패턴에 뛰어들기
스프링 입문을 위한 객체지향의 원리와 이해