Design pattern/행동 패턴

[디자인 패턴] 22장 템플릿 메서드 패턴

미스터로즈 2021. 6. 17. 18:54

공부하기 위해서 요약정리해놓은 것입니다..

 

정확하고 꼼꼼한 자료는 쉽게 배워 바로 써먹는 디자인 패턴을 확인하시고

코드는 github.com/infohojin/patterns 을 참고해 주세요.

 

템플릿 메서드 패턴은 메서드를 이용해 각 단계를 템플릿 구조화하고 행동을 구분합니다.

 

 

프로그램의 구조

 

프로그램의 코드는 구조를 갖고 있습니다.

시작을 기준으로 하여 순차적으로 코드를 읽고 해석합니다.

프로그램이 순차적으로 실행된다는 의미는 단계적으로 코드를 따라간다는 것입니다.

 

모든 행동에는 순서가 있으며, 프로그램은 이러한 동작을 분석해서 순차적으로 연결합니다.

 

인간은 어떤 행동을 추상화하고 이를 이해합니다. 또한 추상화된 각 단계의 동작을 무의식적으로 학습된 형태로 반복합니다.

 

프로그래밍은 복잡한 동작을 단계별로, 구체적으로 구분하여 나열하는 것입니다.

컴퓨터는 동작을 하나씩 지정해서 실행해야 하므로 컴퓨터 프로그램을 바르게 작성하는 것은 각각의 단계를 잘 구별하는 것이라고 할 수 있습니다.

 

<?php

class SandWich
{
    public function make()
    {
        // 단계1 : 빵을 하나 준비합니다.
        $food = "빵";
        
        // 단계2 : 준비된 빵에 속재료를 놀려 놓습니다.
        $food .= " + ";
        $food .= "속재료";
        
        // 단계3 : 속재료 위에 다시 빵하나를 놓습니다.
        $food .= " + ";
        $food .= "빵";

        // 생성된 샌드위치를 반환합니다.
        return $food;
    }
}

샌드위치 생성 방법을 단계적으로 분리했습니다. 

 

템플릿

모든 샌드위치는 공통된 모양의 형틀을 갖고 있고 샌드위치를 만드는 원리와 만들어진 모습이 같습니다.

 

공통된 특징을 적용해 샌드위치 생성 과정을 단계별로 분리합니다.

 

 

 

<?php

class SandWich
{
    public function make()
    {
        // 단계1 : 빵을 하나 준비합니다.
        $food = $this->bread();
        
        // 단계2 : 준비된 빵에 속재료를 놀려 놓습니다.
        $food .= " + ";
        $food .= $this->jam();
        
        // 단계3 : 속재료 위에 다시 빵하나를 놓습니다.
        $food .= " + ";
        $food .= $this->bread();

        // 생성된 샌드위치를 반환합니다.
        return $food;
    }

    public function bread()
    {
        return "식빵";
    }

    public function jam()
    {
        return "딸기쨈";
    }

}

 

샌드위치를 만들기 위한 원재료를 메서드로 분리했습니다. make() 메서드가 재료에 해당하는 메서드를 호출하지만 공통된 단계별 과정에는 변함이 없습니다.

 

객체지향에서의 템플릿은 공통된 처리 로직을 말합니다.

 

일반화

클래스의 일반화는 공통점을 찾아 상위 클래스로 도출하는 과정입니다. 공통점을 기준으로 1개의 클래스를 2개의 클래스로 분리합니다.

 

일반화는 공통된 부분과 다른 부분을 분리합니다.

다양한 클래스로 객체를 확장할 때 공통된 부분만 모아서 별도로 관리하면 추후 유지 보수하기가 편합니다.

 

공통된 부분 -> sandwich.php

<?php
/**
 * 공통된 부분
 */
class SandWich
{
    public function make()
    {
        // 단계1 : 빵을 하나 준비합니다.
        $food = $this->bread();
        
        // 단계2 : 준비된 빵에 속재료를 놀려 놓습니다.
        $food .= " + ";
        $food .= $this->jam();
        
        // 단계3 : 속재료 위에 다시 빵하나를 놓습니다.
        $food .= " + ";
        $food .= $this->bread();

        // 생성된 샌드위치를 반환합니다.
        return $food;
    }
}

 

공통되지 않은 부분은 하위 클래스에 위임합니다. 상위 클래스의 템플릿 메서드는 하위 클래스의 메서드를 호출하여 사용합니다.

 

템플릿 메서드에서는 불필요한 접근을 제한하고 템플릿 접근만 허용합니다.

 

하위클래스는 상위 클래스를 상속받으므로 외부에서 불필요한 메서드가 접근하는 것을 제한합니다.

<?php
/**
 * 공통되지 않은 부분
 */
class Strawberry extends SandWich
{
    protected function bread()
    {
        return "식빵";
    }

    protected function jam()
    {
        return "딸기쨈";
    }
}

 

추상화

템플릿 메서드 패턴은 추상 클래스의 특징을 잘 활용하여 적용한 디자인 패턴입니다.

<?php
/**
 * 공통되지 않은 부분
 */
class StrawberryBagel extends Strawberry
{
    protected function bread()
    {
        return "베이글";
    }
}

 

일반적인 상속 구조를 추상 클래스 구조로 변경합니다. 상위 일반 클래스에 abstract 키워드만 추가하면 SandWich 클래스를 추상 클래스로 변경할 수 있습니다.

 

<?php
/**
 * 공통된 부분
 */
abstract class SandWich
{
    // 템플릿
    public function make()
    {
        // 단계1 : 빵을 하나 준비합니다.
        $food = $this->bread();
        
        // 단계2 : 준비된 빵에 속재료를 놀려 놓습니다.
        $food .= " + ";
        $food .= $this->jam();
        
        // 단계3 : 속재료 위에 다시 빵하나를 놓습니다.
        $food .= " + ";
        $food .= $this->bread();

        // 생성된 샌드위치를 반환합니다.
        return $food;
    }

    // 추상메소드
    abstract protected function bread();
    abstract protected function jam();
}

추상 클래스도 동일한 상속 구조로 결합됩니다.

 

 

템플릿 메서드

템플릿 메서드는 공통된 로직을 분리하여 캡슐화합니다. 공통 단계인 템플릿을 별도의 메서드로 작성합니다.

 

템플릿 메서드 패턴은 알고리즘과 같은 동작을 적용할 때 유용한 패턴입니다. 단계를 미리 정해놓고, 실제 구체적인 내용은 하위 클래스에게 요청합니다.

 

하위 클래스에서 구현되는 메서드를 후크 메서드라고 합니다. 후크는 중복된 코드를 제거하고 처리 로직의 일부를 변경할 때 자주 사용하는 기법입니다.

 

템플릿 메서드는 추상 클래스를 통해 호출 방식을 미리 정의하고 하위 클래스에서 실체를 구현합니다.

 

 

템플릿 메서드 패턴에서는 구성 요소간 상호 의존성이 발생합니다.

 

템플릿 메서드는 할리우드 원칙이라는 역전 제어 구조를 사용하는데, 높은 수준의 구성 요소가 낮은 수준의 구성 요소에 의존합니다.