상세 컨텐츠

본문 제목

탬플릿 메서드 패턴(Template Method Pattern)/스프링 입문을 위한 자바 객체 지향의 원리와 이해-06스프링이 사랑한 디자인 패턴

본문

728x90

탬플릿 메서드 패턴

우리는 객체 지향의 4대 특성 가운데 상속을 통해 동일한 부분(중복)은 상위 클래스로, 달라지는 부분만 하위 클래스로 분할한다.

 

객체 지향 4대 특성은? 스프링 입문을 위한 자바 객체 지향의 원리와 이해 p.79를 보면 객체 지향 4대 특성은 다음과 같다.

캡-캡슐화(Encapsulation) : 정보 은닉(Information hiding)

상-상속(Inheritance) : 재사용

추-추상화(Abstraction): 모델링

다-다형성(Polymorphism): 사용 편의

 

따라서, 예제 6-19 Dog.java와 예제 6-20 Cat.java의 공통된 부분을 상위 클래스로 설계하게 된다.

예제 6-21 상위 클래스를 포함하는 Animal.java

package templateMethodPattern;

public abstract class Animal {
	// 탬플릿 메서드
	public void playWithOwner() {
    	System.out.println("귀염둥이 이리온...");
        play();
        runSomething();
        System.out.println("잘했어");
	}
    
    // 추상 메서드
    abstract void play(); // 하위 클래스에서 꼭 구현을 해야한다.
    
    // Hook(갈고리) 메서드
    void runSomething() {
    	System.out.println("꼬리 살랑 살랑~");
    }
}

Animal 클래스는 추상(abstract) 메소드를 담고 있기에 추상(abstract) 클래스다.

상위 클래스인 Animal에는 템플릿(견본)을 제공하는 playWithOwner() 메서드와 하위 클래스에게 구현을 강제하는 play() 추상 메서드, 하위 클래스가 선택적으로 오버라이딩할 수 있는 runSomething() 메서드가 있다.

 

예제 6-22 하위 클래스를 포함하는 Dog.java

package templateMethodPattern;

public class Dog extends Animal {
	@Override
    // 추상 메서드 오버라이딩
    void play() {
    	System.out.println("멍! 멍!");
    }
    
    @Override
    // Hook(갈고리) 메서드 오버라이딩
    void runSomething() {
    	System.out.println("멍! 멍!~ 꼬리 살랑 살랑~");
    }
}

 

예제 6-23 하위 클래스를 포함하는 Cat.java

package templateMethodPattern;

public class Cat extends Animal {
	@Override
    // 추상 메서드 오버라이딩
    void play() {
    	System.out.println("야옹~ 야옹~");
    }
    
    @Override
    // Hook(갈고리) 메서드 오버라이딩
    void runSomething() {
    	System.out.println("야옹~ 야옹~ 꼬리 살랑 살랑~");
    }
}

 

앞에서

상위 클래스인 Animal에는 템플릿(견본)을 제공하는 playWithOwner() 메서드와 하위 클래스에게 구현을 강제하는 play() 추상 메서드, 하위 클래스가 선택적으로 오버라이딩할 수 있는 runSomething() 메서드가 있다.

라고 언급했는데

이처럼 상위 클래스에 공통 로직을 수행하는 템플릿 메서드하위 클래스에 오버라이딩을 강제하는 추상 메서드 또는 선택적으로 오버라이딩할 수 있는 훅(Hook) 메서드를 두는 패턴을 템플릿 메서드 패턴이라고 한다.

 

템플릿 메서드 패턴의 구성 요소

-> 탬플릿 메서드) 공통 로직을 수행, 로직 중에 하위 클래스에서 오버라이딩한 추상 메서드/훅 메서드를 호출

따라서 playWithOwner는 다음과 같이 추상 메서드와 훅 메서드를 호출한다.

public abstract class Animal {
	// 탬플릿 메서드
	public void playWithOwner() {
    	System.out.println("귀염둥이 이리온...");
        play();
        runSomething();
        System.out.println("잘했어");
	}
    ...(중략)
}

->탬플릿 메서드에서 호출하는 추상 메서드) 하위 클래스가 반드시 오버라이딩 해야 한다.

예시) 상위 클래스 Animal의 메서드 abstract void play()

 

->탬플릿 메서드에서 호출하는 훅(Hook, 갈고리 메서드) 하위 클래스가 선택적으로 오버라이딩 한다.

예시) 상위 클래스 Animal의 메서드 runSomething()

 

템플릿 메서드 패턴-"상위 클래스의 견본 메서드에서 하위 클래스가 오버라이딩한 메서드를 호출하는 패턴"

 

클래스 다이어그램을 보면 탬플릿 메서드 패턴이 의존 역전 원칙(DIP)를 활용하고 있음을 알 수 있다.

=>구체적인 동물의 이름 클래스(Cat, Dog 등등)이 추상화된 동물 클래스에 의존하고 있다.

 

[예제 6-24] Driver.java

package templateMethodPattern;
public class Driver {
	public static void main(String[] args) {
    	Animal bolt = new Dog();
        Animal kitty = new Cat();
        
        bolt.playwithOwner(); // Animal형 bolt->오버라이딩 된 추상메서드 호출
        //Animal형 bolt->훅 메서드 호출
        
        System.out.println();
        System.out.println();
        
        kitty.playWithOwner(); //Animal형 kitty->오버라이딩 된 추상메서드 호출
        //Animal형 kitty->훅 메서드 호출
    }
 }

1. 템플릿 메서드 호출 Driver 클래스 내부 main 함수의 코드 bolt.playWithOwner();

Animal형 변수 bolt여서 ->2.오버라이딩 된 추상메서드 호출
Animal형 bolt->3.훅 메서드 호출


4.템플릿 메서드 호출kitty.playWithOwner();

Animal형 변수 kitty여서->5.오버라이딩 된 추상메서드 호출
Animal형 kitty->6.훅 메서드 호출

 

템플릿 메서드 패턴이란

"상위 클래스의 견본 메서드에서 하위 클래스가 오버라이딩한 메서드를 호출하는 패턴"

 

DIP-의존 역전 원칙이란? 구체적인 것이 추상화된 것에 의존하게 하는 것

(자세한 내용은 p.195 참고)

그림 5-16)자동차 클래스가 스노우타이어 클래스(자주 변경되는 구체 클래스 특징을 가짐)에 의존하면 구체적인 클래스에 의존하게 되는 것이여서 DIP에 맞지 않는다.

그림 5-17처럼 자동차가 구체적인 타이어 클래스(스노우타이어, 일반타이어, 광폭타이어)에 의존하지 않고 추상화된 타이어 인터페이스에만 의존하게 하면 스노우타이어에서 일반타이어로, 또는 다른 구체적인 타이어로 변경돼도 자동차는 그 영향을 받지 않는다.

그림 5-17에서는 5-16과 달리, 구체적인 것이 추상화된 것에 의존하는 것으로 의존의 방향이 역전되었다.

결국, 자동차 클래스는 자신보다 변하기 쉬운 스노우타이어에 의존하던 관계(그림 5-16 예시)를 중간에 추상화된 타이어 인터페이스를 추가해 두고 의존 관계를 역전했다.

 

출처)스프링 입문을 위한 자바 객체 지향의 원리와 이해(김종민 저)-06스프링이 사랑한 디자인 패턴

728x90

관련글 더보기

댓글 영역