템플릿 메서드 형성

하위클래스 안의 두 메서드가 거의 비슷한 단계들을 같은 순서로 수행할 땐
그 단계들을 시그니처가 같은 두 개의 메서드로 만들어서 두 원본 메서드를 같게 만든 후,
두 메서드를 상위클래스로 옮긴다

동기

  • 하위 클래스에 있는 두 메서드가 비슷하다면 둘을 합쳐서 하나의 상위 클래스로 만드는것이 좋다
  • 두 메서드가 완전히 똑같지 않다면, 중복된 부분은 가능한 한 전부 없애고 차이가 있는 필수 부분만 그대로 둬야한다

방법

  1. 비슷해보이는 같은 클래스에 있다면, 두 메서드가 어떤 공통 상위클래스의 하위클래스가 되게 정리해야 한다

    1
    2
    3
    4
    5
    6
    7
    8
    9
    class Printer {
    public String textPrint() {
    // ...
    }

    public String imagePrint() {
    // ...
    }
    }

    를 아래의 구조로 변경한다

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    class Printer {
    public String textPrint() {
    return new TextPrinter().print();
    }

    public String imagePrint() {
    return new ImagePrinter().print();
    }
    }
    class TextPrinter extends Printer {
    public String print() {
    // ...
    }
    }
    class ImagePrinter extends Printer {
    public String print() {
    // ...
    }
    }
    • 리팩토링은 작게작게 진행해야하므로, 하위클래스에 위임하는 방식으로 구현했다
    • 메서드상향이 용이하도록 두 하위클래스의 메서드명을 같게했다
  2. 두 메서드를 잘게 분리하는데, 공통된 부분과 공통되지 않은 부분이 나오게끔 분리한다

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    class TextPrinter extends Printer {
    public String print() {
    // ...
    printBody();
    // ...
    }
    public String printBody() {
    // 다른 부분
    }
    }
    class ImagePrinter extends Printer {
    public String print() {
    // ...
    printBody();
    // ...
    }
    public String printBody() {
    // 다른 부분
    }
    }

    이 기법의 핵심이다

  3. 하나의 클래스에 대해 메서드 상향을 실시하자

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    abstract class Printer {
    public String print() {
    // ...
    printBody();
    // ...
    }
    public abstract String printBody(); // 달랐던 부분
    }
    class TextPrinter extends Printer {
    public String printBody() {
    // 다른 부분
    }
    }
    • 달랐던 부분은 abstract로 선언하고, 하위클래스에서 구현하도록 한다
    • 위임하던 코드는 삭제한다
  4. 나머지 하나의 클래스에도 동일하게 적용한다

참고 : 마틴 파울러, 『리팩토링』, 김지원 옮김, 한빛미디어(2012)