티스토리 뷰

반응형

템플릿 메소드 패턴 (Template Method Pattern)

 알고리즘의 골격을 정의하는 패턴입니다. 템플릿 메소드를 사용하면 부모 클래스의 알고리즘 골격을 그대로 유지하면서 알고리즘의 특정 단계를 서브클래스에서 재정의할 수 있습니다.

 

 

구조

출처: https://refactoring.guru/ko/design-patterns/template-method

1. 추상 클래스: 알고리즘의 단계들을 선언하고, 이 메서드들을 순서대로 호출하는 템플릿 메서드도 함께 선언합니다. 알고리즘 중 일부는 구현되어 있을 수도 있어요!

2. 구상 클래스: 추상 클래스의 알고리즘들을 재정의할 수 있지만 템플릿 메서드를 재정의할 수는 없습니다.

 

예시

 책에서는 카페인이 함유된 음료를 의미하는 CaffeinBeverage 추상 클래스를 예시로 들고 있습니다.

 

 prepareRecipe() 메소드는 음료를 준비하는 순서대로 알고리즘을 실행하는 템플릿(틀) 메소드입니다. 음료 준비 과정은 물 끓이기 → 우리기 → 컵에 붓기 → 첨가물 추가하기 순으로 이루어집니다.

 

물을 끓이는 boilWater(), 컵에 물을 붓는 pourInCup() 메소드는 추상 클래스에서 구현하고, 차를 우리는 brew(), 첨가물을 넣는 addCondiments() 메소드는 서브클래스에서 처리하기 위해 추상 메소드로 선언합니다.

 

public abstract class CaffeinBeverage {
    final void prepareRecipe() {
        boilWater();
        brew();
        pourInCup();
        addCondiments();
    }
    
    abstract void brew();
    
    abstract void addCondiments();
    
    void boilWater() {
        // ...
    }
    
    void pourInCup() {
        // ...
    }
    
    void hook() {}
}

 

카페인을 함유하고 있는 대표 음료인 Coffee와 Tea 구상 클래스를 만들어보겠습니다. 이 구상 클래스는 CaffeinBeverage 클래스를 상속해 구현할 수 있습니다. 커피와 차를 우리는 과정과 음료에 들어가는 첨가물이 다르기 때문에 brew(),  addCondiments() 메소드를 각 음료에 맞게 구현해줍니다. 이제 우리는 두 음료를 prepareRecipe() 템플릿 메소드로 한 번에 준비할 수 있게 되었습니다. 

 

 

후크(hook) 는 뭐에요?

추상 클래스에서 선언된, 아무 코드도 들어가지 않은 메소드를 후크라고 부릅니다.

필요한 경우에만 구현 클래스에서 후크를 재정의해 입맛에 맞게 수정할 수 있습니다.

 

 

예제를 한 번 볼게요!

손님이 첨가물을 원하는 경우에만 음료에 첨가물을 넣도록 코드를 수정해볼까요?

customerWantsCondiments() 메소드를 후크로 사용하겠습니다.

public abstract class CaffeinBeverageWithHook {
    final void prepareRecipe() {
        boilWater();
        brew();
        pourInCup();
        if (customerWantsCondiments()) {
            addCondiments();        
        }
    }
    
    abstract void brew();
    
    abstract void addCondiments();
    
    void boilWater() {
        // ...
    }
    
    void pourInCup() {
        // ...
    }
    
    boolean customerWantsCondiments() {
        return true;
    }
}

 

 customerWantsCondiments()는 true만 리턴하는 기본적인 후크 메소드입니다. customerWantsCondiments()는 필요한 경우에만 서브클래스에서 오버라이드해 첨가물을 추가할지 여부를 입력받는 코드로 수정하여 사용할 수 있습니다.

 

 

 

후크 ↔️ 추상 메소드

추상 메소드: 서브클래스가 알고리즘 특정 단계를제공해야 할 때 사용합니다.

후크: 서브클래스가 알고리즘 특정 단계를 선택적으로 제공해야 할 때 사용합니다.

 

 후크는 앞에서 든 예제처럼 주로 템플릿 메소드에서 앞으로 일어날 일, 또는 막 일어난 일에 서브클래스가 반응할 수 있도록 기회를 제공하는 용도로 쓰일 수 있습니다.

 

 


 

할리우드 원칙 (Hollywood Principle)

먼저 연락하지 마세요. 저희가 연락드리겠습니다.

 

...ㅋㅋㅋㅋㅋㅋㅋㅋ네...

 

이 할리우드 원칙을 활용하면 의존성 부패를 방지할 수 있다고 합니다. 고수준 구성 요소가 저수준 구성 요소에 의존하고, 저수준 구성 요소가 다시 고수준 구성 요소에 의존하는 것처럼 의존성이 복잡하께 꼬인 것을 의존성이 부패했다고 말하는데요. 즉, 고수준 구성 요소가 저수준 구성 요소에게 "먼저 연락하지 마세요. 제가 연락드리겠습니다."라고 얘기하는 것이 할리우드 원칙이라고 하네요!

 

템플릿 메소드 패턴에도 할리우드 원칙이 적용되어 있는데요. CaffeinBeverage라는 추상 클래스가 음료를 만드는 방법 알고리즘을 장악하고 있고, 메소드 구현이 필요한 상황에만 저수준 구성 요소인 서브 클래스를 불러내고 있기 때문입니다.

 

 

 

 

 

 

 

헤드 퍼스트 디자인 패턴 - YES24

유지관리가 편리한 객체지향 소프트웨어 만들기!“『헤드 퍼스트 디자인 패턴(개정판)』 한 권이면 충분하다.이유 1. 흥미로운 이야기와 재치 넘치는 구성이 담긴 〈헤드 퍼스트〉 시리즈! 하나

www.yes24.com

 

반응형