템플릿 메소드 패턴

오형민·2021년 7월 19일
0

디자인패턴

목록 보기
2/6

예제부터

public class Coffee {
    // 커피 만드는 방법
    void prepareRecipe() {
        boilWater();
        brewCoffeeGrinds();
        pourInCup();
        addSugarAndMilk();
    }
    public void boilWater() {
        System.out.println("물 끓이는 중");
    }
    public void brewCoffeeGrinds() {
        System.out.println("필터를 통해서 커피를 우려내는 중");
    }
    public void pourInCup() {
        System.out.println("컵에 따르는 중");
    }
    public void addSugarAndMilk() {
        System.out.println("설탕과 우유를 추가하는 중");
    }
}
public class Tea {
    // 홍차 만드는 방법
    void prepareRecipe() {
        boilWater();
        steepTeaBag();
        pourInCup();
        addLemon();
    }
    public void boilWater() {
        System.out.println("물 끓이는 중");
    }
    public void steepTeaBag() {
        System.out.println("차를 우려내는 중");
    }
    public void pourInCup() {
        System.out.println("컵에 따르는 중");
    }
    public void addLemon() {
        System.out.println("레몬을 추가하는 중");
    }
}
  • 겹치는 부분이 많음

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

  • 템플릿 메소드 패턴(Template Method Pattern)에서는 알고리즘의 골격을 정의합니다. 알고리즘의 여러 단계 중 일부는 서브클래스에서 구현할 수 있습니다. 템플릿 메소드를 이용하면 알고리즘의 구조는 그대로 유지하면서 서브클래스에서 특정 단계를 재정의할 수 있습니다.

용어

  • 템플릿 메소드
    - 필수 처리 절차를 정의한 메소드.
    - 서브클래스가 오버라이드하는 추상 메소드들을 사용하여 알고리즘을 정의하는 메소드.
  • 훅 연산(hook operation)
    - 필요하다면 서브클래스에서 확장할 수 있는 기본적인 행동을 제공하는 연산(메소드).
    - 기본적으로는 아무 내용도 정의하지 않는다.
  • 헐리우드 원칙
    - 먼저 연락하지 마세요. 저희가 연락 드리겠습니다 .
    - 헐리우드 원칙을 활용하면 "의존성 부패(dependency rot)"를 방지할 수 있습니다. 의존성이 복잡하게 꼬여있는 것을 의존성 부패라고 부릅니다. 의존성이 부패되면 시스템이 어떤 식으로 디자인된 것인지 거의 아무도 알아볼 수 없게 됩니다. 템플릿 메소드 패턴은 헐리우드 원칙을 적용한 패턴이라고 할 수 있습니다.

기본 구조

  • 알고리즘은 final로 지정하여 서브클래스에서 수정할 수 없도록 하였습니다.
  • 알고리즘의 일부 구현은 서브클래스에서 담당하도록 합니다.
  • hook() 다양한 용도로 사용할 수 있습니다.
public abstract class AbstractClass {

    final void templateMethod() {
        primitiveOperation1();
        primitiveOperation2();
        concreteOperation();
        hook();
    }

    abstract void primitiveOperation1();

    abstract void primitiveOperation2();

    final void concreteOperation() {}

    void hook() {}
}

예제 수정

공통적인 부분을 뽑아 추상 클래스를 만든다.

  • 알고리즘의 세부 항목에서 차이가 있는 곳은 추상 메소드로 정의한다.
public abstract class CaffeineBeverage {
    // 알고리즘을 갖고 있는 이 메소드를 '템플릿 메소드'라 부른다
    final void prepareRecipe() {
        boilWater();
        brew();
        pourInCup();
        addCondiments();
    }

    abstract void brew();           // 서브클래스에서 구현
    abstract void addCondiments();  // 서브클래스에서 구현

    void boilWater() {
        System.out.println("물 끓이는 중");
    }
    void pourInCup() {
        System.out.println("컵에 따르는 중");
    }
}
public class Coffee extends CaffeineBeverage {
    public void brew() {
        System.out.println("필터로 커피를 우려내는 중");
    }
    public void addCondiments() {
        System.out.println("설탕과 커피를 추가하는 중");
    }
}
public class Tea extends CaffeineBeverage {
    public void brew() {
        System.out.println("차를 우려내는 중");
    }
    public void addCondiments() {
        System.out.println("레몬을 추가하는 중");
    }
}

hook을 더하면...

public abstract class CaffeineBeverage {
    // 알고리즘을 갖고 있는 이 메소드를 '템플릿 메소드'라 부른다
    final void prepareRecipe() {
        boilWater();
        brew();
        pourInCup();
        // 고객이 원하는 경우에만 첨가물을 넣는다
        if (customerWantsCondiments()) {
            addCondiments();
        }
    }

    abstract void brew();           // 서브클래스에서 구현
    abstract void addCondiments();  // 서브클래스에서 구현

    void boilWater() {
        System.out.println("물 끓이는 중");
    }
    void pourInCup() {
        System.out.println("컵에 따르는 중");
    }

    // 이 메소드가 hook 메소드
    boolean customerWantsCondiments() {
        return true;
    }
}

추가 참조 예제

기계인간 블로그

장단점

장점

  • 큰 알고리즘에서 수정이 필요한 경우, 해당하는 부분에 대해서만 수정하도록 할 수 있으므로, 그 외 부분의 수정에 대한 영향도를 적게 가져갈 수 있음

단점

  • 수정 가능 범위를 좁혀야 하므로, 일부 클라이언트에게 맞지 않을 수 있음.
  • Liskov Substitution Principle를 위반할 여지가 충분함.
    - 상위 객체의 뼈대가 중요하기 때문
  • 만약 알고리즘 뼈대에서 추가 단계를 삽입하고자 한다면, 다른 디자인 패턴에 비해 품이 많이 들어갈 수 있음.

생각해볼문제

  • 문서 추출 및 파싱
    - Doc, CSV, pdf, hwp, txt 파일에 대해 문자열 추출 및 파싱을 진행해야 함
    • 문서를 여는 방법, 파싱 마무리된 데이터 분석, 파일 전송(보고), 파일 닫기 로직은 동일
    • 파일에서 문서 추출하는 방법, 추출된 데이터를 파싱하는 방법은 파일 형식마다 다름
    • hwp 파일의 경우, 별도의 방법을 사용하고 있어 파싱 마무리 후 데이터 분석 전 별도로 인코딩을 진행해주어야 함
      - 순서는 파일 열기 -> 파일에서 문서 추출 -> 추출된 문서 파싱 -> 파싱된 데이터 분석 -> 보고 -> 파일 닫기 순으로 진행

0개의 댓글