디자인 패턴 (Design Pattern)

[행동 패턴] 템플릿 메서드(Template Method)

계란💕 2023. 2. 27. 16:36

템플릿 메서드(Template Method)

  • Def) 알고리즘의 구조메소드에 정의하고 하위 클래스에서 알고리즘 구조의 변경없이 알고리즘을 재정의하는 패턴
    • 부모 클래스에서 알고리즘의 골격을 정의하지만 해당 알고리즘의 구조를 변경하지 않고 자식 클래스들이 알고리즘의 특정 단계를 오버라이드할 수 있도록 하는 행동 디자인 패턴을 말한다. 
  • 사용하는 경우
    • 구현하려는 알고리즘이 일정한 프로세스가 있다. 여러 단계가 있다. 
    • 구현하려는 알고리즘이 변경 가능성이 있다. 

 


템플릿 메서드 사용 방법

  1. 알고리즘을 여러 단계로 나눈다. 
  2. 나눠진 알고리즘의 단계를 메소드로 선언한다. 
  3. 알고리즘을 수행한 템플릿 메소드를 만든다. 
  4. 하위 클래스에서 나눠진 메소드들오버라이드한다. 

 

 


기본 설계

  • 추상 클래스에 step1, 2, 3 을 나눠서 다음과 같이 추상 메서드로 선언한다. 
  • step1, 2, 3에 해당하는 메서드들을 템플릿 메서드에서 호출한다. 
    • 즉, 템플릿 메서드는 구현부가 있다. 
  • 하위 클래스에서 메서드를 재정의한다. 

 


  Ex) 신작 게임의 접속을 구현하라

  • 보안 과정: 보안 관련 부분을 처리한다.
  • 인증 과정: user name과 password가 일치하는지 확인한다. 
  • 권한 과정: 접속자가 유료 회원인지 무료 회원인지 게임 마스터인지 확인한다. 
  • 접속 과정: 접속자에게 커넥션을 정보로 넘겨준다. 

 

 

  • 추상 클래스 구현하기 - abstractGameHelper
    • 하위 클래스가 메서드들을 재정의해야하므로 접근 제어자를 private로 설정하지 않는다. 
    • request 메서드는 네 가지 단계(보안, 인증, 권한, 접속)로 이뤄져 있다. 
    • 메서드 패턴에서 네 가지를 불러준다.
<hide/>
public abstract class AbstractGameConnectHelper {


    protected abstract String doSecurity(String string);

    protected abstract boolean authorization(String id, String password);

    protected abstract int authorization(String username);

    protected abstract String connection(String info);


    // 템플릿 메서드
    public String requestConnection(String encodedInfo) {

        String decodedInfo = doSecurity(encodedInfo);    // 보안 작업 => 암호화된 문자열을 복호화
        String id = "userId";
        String password = "1234!@";

        if (!authorization(id, password)) {
            throw new Error("아이디 암호 불일치");
        }

        String userName = "userName";
        int authIndex = authorization(userName);   // 권한 번호

        switch (authIndex) {
            case 0:     // 게임 매니저
                break;

            case 1:     // 유료 회원
                break;

            case 2:     // 무료 회원
                break;

            case 3:     // 권한 없음
                break;

            default:    // 기타 상황
                break;
        }

        return connection(decodedInfo);
    }
}

 

  • 구체화 클래스 DefaultGameConnectHelper
    • 하위 클래스에서 구현해준다. 
    • 패키지를 따로 나눠서 클래스를 분리해주면  위에서 protected로 접근 제한자를  지정해줬기 때문에 다음 코드의 helper 까지 구현했을 때, request 를 제외한 다른 메서드는 나오지 않는다. 
<hide/>
package dp;

public class DefaultGameConnectHelper extends AbstractGameConnectHelper {
    @Override
    protected String doSecurity(String string) {
        System.out.println("= decode =");
        return null;
    }

    protected boolean authentication(String id, String password) {
        System.out.println("= 아이디/암호 확인 과정");
        return true;
    }

    @Override
    protected int authorization(String username) {
        System.out.println("= 권한 확인 =");
        // 서버에서 유저  이름을 가지고 나이를 확인해서 시간을 확인하고 성인이 아니고 10시가 지났다면
        // 권한이 없는 것으로
        return -1;
    }

    @Override
    protected String connection(String info) {
        System.out.println("= 마지막 접속 단계! =");
        return null;
    }
}

 

 

  • Main
<hide/>
public static void main(String[] args) {

    AbstractGameConnectHelper helper = new DefaultGameConnectHelper();
    helper.requestConnection("아이디 암호 등 접속 정보");
}

 


  Ex) 추가 요구 사항 - 셧다운제

  • 보안 부분 강화
  • 밤 10시 이후 접속이 제한 되도록 한다. 
  • Default 클래스를 다음과 같이 바꾼다. 
<hide/>
@Override
protected int authorization(String username) {
    System.out.println("= 권한 확인 =");
    // 서버에서 유저  이름을 가지고 나이를 확인해서 시간을 확인하고 성인이 아니고 10시가 지났다면
    // 권한이 없는 것으로
    return -1;
}
case -1:     //
    throw new Error("셧다운");

 


궁금한 점 및 기타

  • 결국 템플릿 메소드 패턴은 데이터베이스의 프로시저와 비슷한 개념?
  • (인터페이스는 추상 메서드로만 이뤄져 있는 것과 다르게 추상클래스에는 멤버 변수, 구현부를 포함한 메서드를 포함할 수 있다.)
  •  

 

 

출처 

https://www.inflearn.com/course/lecture?courseSlug=%EC%9E%90%EB%B0%94-%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4&unitId=3175