블로그를 이전하였습니다. 2023년 11월부터 https://bluemiv.github.io/에서 블로그를 운영하려고 합니다. 앞으로 해당 블로그의 댓글은 읽지 못할 수 도 있으니 양해바랍니다.
반응형
Template Method Pattern
템플릿 메소드 패턴은 일정한 구조의 프로세스를 가진 경우, 사용하기 좋은 디자인 패턴
- 코드의 중복을 줄일 수 있고 유지보수하기에도 편리함.
일정한 구조의 프로세스?
- 특정 알고리즘이 A -> B -> C 와 같이 항상 A 작업을 수행하고, B작업, C작업을 수행한다면, 각 작업들을 메소드로 구현한다.
- A -> B -> C 순으로 실행되도록 실행 메소드를 구현한다. (아래 수도코드 참고)
func doA:
// A 로직 수행
func doB:
// B 로직 수행
func doC:
// C 로직 수행
func doSomething:
doA
doB
doC
예제
요구사항
계정 로그인을 한다.
로그인의 동작 순서는 아래와 같다.
- 사용자의 아이디, 비밀번호 복호화
- 유효한 아이디와 비밀번호인지 확인
- 권한 확인
- 접속
Template Method 작성
public abstract class ConnectionManager {
protected abstract Map<String, String> decodedUerInfo(Map<String, String> rawUserInfo);
protected abstract boolean authentication(String username, String password);
protected abstract int authorization(String username);
protected abstract Object getConnection(String username, int authority);
public Object requestConnection(Map<String, String> rawUserInfo) {
// 1. 암호화 된 유저 정보를 복호화한다.
final Map<String, String> userInfo = decodedUerInfo(rawUserInfo);
final String username = userInfo.get("username");
final String password = userInfo.get("password");
// 2. 아이디와 패스워드를 인증한다.
if (!authentication(username, password)) {
throw new RuntimeException("인증 실패!");
}
// 3. 권한을 확인한다.
final int authority = authorization(username);
// 4. 서비스에 접속한다.
return getConnection(username, authority);
}
}
- '계정 접속'을 위한 4단계를 추상 메소드로 만든다.
- 이때, 4단계에 대한 각 작업은 protected 권한을 주어 상속 받은 객체에서만 구현할 수 있도록 한다.
- requestConnection() 메소드를 통해 위 4단계를 차례대로 수행한다.
세부 기능 구현
public class DefaultConnection extends ConnectionManager {
@Override
protected Map<String, String> decodedUerInfo(Map<String, String> rawUserInfo) {
System.out.println("유저 정보 복호화");
final Map<String, String> encodedUserInfo = rawUserInfo; // 복호화를 했다고 가정
return encodedUserInfo;
}
@Override
protected boolean authentication(String username, String password) {
System.out.println("유저 정보 인증 확인");
if("hong".equals(username)) {
return true;
}
return false;
}
@Override
protected int authorization(String username) {
System.out.println("권한 정보 확인");
// DB에서 권한을 가져온다.
int authority = 0;
if("hong".equals(username)) {
authority = 1;
}
// 권한에 따른 작업 수행
switch (authority) {
case 0:
System.out.println("- 권한: 일반 사용자");
break;
case 1:
System.out.println("- 권한: 관리자");
break;
case 2:
System.out.println("- 권한: 슈퍼 관리자");
break;
default:
throw new RuntimeException("올바르지 않은 권한!");
}
return authority;
}
@Override
protected Object getConnection(String username, int authority) {
System.out.println(username + " 접속!");
final Object connectionObj = new Object();
return connectionObj; // Connection 객체 반환
}
}
- 위에서 만든 추상 클래스의 추상 메소드('접속'을 위한 4단계)를 구현한다.
- 위 예제는 단순히 '템플릿 메소드 패턴'에 대한 내용을 소개하기 위한 용도로, 상세 내용은 구현하지 않음
Main 클래스 구현
public class Main {
public static void main(String[] args) {
final ConnectionManager cm = new DefaultConnection();
final Map<String, String> userInfo = new HashMap<>();
userInfo.put("username", "hong");
userInfo.put("password", "12341234");
final Object connectionObj = cm.requestConnection(userInfo);
}
}
유저 정보 복호화
유저 정보 인증 확인
권한 정보 확인
- 권한: 관리자
접속!
- requestConnection() 메소드 하나를 호출하면 4단계를 모두 수행함.
응용
만약 휴면계정일때는 본인 확인이 필요하여 접속을 거부해야한다면?
public class DefaultConnection extends ConnectionManager {
// ...
@Override
protected int authorization(String username) {
System.out.println("권한 정보 확인");
// DB에서 권한을 가져온다.
int authority = 0;
if("hong".equals(username)) {
authority = 1;
}
// 권한에 따른 작업 수행
switch (authority) {
case -1: // 휴면 계정에 대한 처리 추가
System.out.println("- 권한: 휴면 계정");
break;
case 0:
System.out.println("- 권한: 일반 사용자");
break;
case 1:
System.out.println("- 권한: 관리자");
break;
case 2:
System.out.println("- 권한: 슈퍼 관리자");
break;
default:
throw new RuntimeException("올바르지 않은 권한!");
}
return authority;
}
// ...
}
- 단순히 4단계 중 관련 기능 메소드만 수정하면 됨.
클래스 다이어그램
반응형
'Study > Design Pattern' 카테고리의 다른 글
Design Pattern - Factory Method Pattern (팩토리 메소드 패턴) (0) | 2020.06.07 |
---|---|
Design Pattern - Strategy Pattern (스트래티지 패턴) (1) | 2020.06.07 |