공통적인 프로세스를 묶어주는 방법이다. 일정한 프로세스의 요구사항을 구현하는 방법이다.
유지보수와 확장성에서 이득을 보게 된다.
- 구현 로직의 일정한 단계를 거친다.
- 구현 로직의 변경 가능성이 크다.
- 로직을 여러 단계로 나눈다.
- 나눈 단계를 메서드로 선언한다.
- 나눈 단계를 수행하는 템플릿 메서드를 만든다.
- 하위 클래스에서 메소드를 구현한다.
가장 중요한 점은 단계를 나눈다는 것이고, 또 기존 프로세스 메서드를 외부에 노출시키지 않는 것이다.
보안, 인증, 인가, 접속 단계를 추상화 / 이를 진행하는 템플릿 메서드 선언
public abstract class AbstractProcessConnection {
// 프로세스 메서드는 공개되지 아니한다.
//보안
protected abstract String[] doSecurity(String encodedStr);
// 인증
protected abstract boolean authentication(String username, String password);
// 인가
protected abstract int authorization(String username, String password);
// 접속
protected abstract String connection(int info);
// 템플릿 메서드는 프로세스 메서드들을 실행시키는 메서드이다.
public String requestConnection(String userinfo){
String[] decodedStrArr = doSecurity(userinfo);
boolean authenticationResult = authentication(decodedStrArr[0], decodedStrArr[1]);
int authorizationResult = 0;
if(authenticationResult){
authorizationResult = authorization(decodedStrArr[0],decodedStrArr[1]);
} else {
new RuntimeException("인증 실패");
}
return connection(authorizationResult);
}
}
프로세스를 구현하는 구현 클래스
public class DefaultProcessConnection extends AbstractProcessConnection {
@Override
protected String[] doSecurity(String encodedStr) {
System.out.println("보안 작업 시작, 디코딩 할 String : "+encodedStr);
try {
String decode = URLDecoder.decode(encodedStr, "UTF-8");
return decode.split("&");
} catch(Exception e){
e.printStackTrace();
}
return null;
}
@Override
protected boolean authentication(String username, String password) {
System.out.println("인증 작업 시작 : "+username +" / "+password);
return (username != null && password != null) ? true : false ;
}
@Override
protected int authorization(String username, String password) {
int result = 0;
switch (username) {
case "ADMIN":
result = 1;
break;
case "MANAGER":
result = 2;
break;
case "USER":
result= 3;
break;
default:
result = 0;
break;
}
System.out.println("인가 결과 : "+result);
return result;
}
@Override
protected String connection(int info) {
String role = null;
switch (info) {
case 1:
role = "ADMIN";
break;
case 2:
break;
case 3:
role = "USER";
break;
default:
role = "NONE";
break;
}
String result = "커넥션 완료, 권한 정보 : " +role+ "/ 접속 시간 : "+new Date().toString() + "/ 사용 중인 스레드 : "+Thread.currentThread().getName();
return result;
}
}
// 메인 메서드
public class Main {
public static void main(String[] args) throws UnsupportedEncodingException {
String encodedInfo = URLEncoder.encode("ADMIN&SOOMIN", "UTF-8");
DefaultProcessConnection defaultProcessConnection = new DefaultProcessConnection();
String result = defaultProcessConnection.requestConnection(encodedInfo);
System.out.println(result);
}
}
// 로그
보안 작업 시작, 디코딩 할 String : ADMIN%26SOOMIN
인증 작업 시작 : ADMIN / SOOMIN
인가 결과 : 1
커넥션 완료, 권한 정보 : ADMIN/ 접속 시간 : Mon Nov 23 23:12:11 KST 2020/ 사용 중인 스레드 : main
만약 밤 10시 이후 접속을 제한해야하는 요구 사항이 생겼다면 확장하거나 유지보수를 해야한다.
확장해야 한다면 추상 클래스를 상속하는 새로운 클래스를 작성하면 되나, 기존 코드를 보수 했다.
public class DefaultProcessConnection extends AbstractProcessConnection {
@Override
protected String[] doSecurity(String encodedStr) {
System.out.println("보안 작업 시작, 디코딩 할 String : "+encodedStr);
try {
String decode = URLDecoder.decode(encodedStr, "UTF-8");
// 추가 로직
int now = new Date().getHours();
if(now > 22) {
return new String[]{"Blocked","None"};
}
return decode.split("&");
} catch(Exception e){
e.printStackTrace();
}
return null;
}
@Override
protected boolean authentication(String username, String password) {
System.out.println("인증 작업 시작 : "+username +" / "+password);
return (username != null && password != null) ? true : false ;
}
@Override
protected int authorization(String username, String password) {
int result = 0;
switch (username) {
case "ADMIN":
result = 1;
break;
case "MANAGER":
result = 2;
break;
case "USER":
result= 3;
break;
//추가
case "Blocked":
result = -1;
break;
default:
result = 0;
break;
}
System.out.println("인가 결과 : "+result);
return result;
}
@Override
protected String connection(int info) {
String role = null;
switch (info) {
case 1:
role = "ADMIN";
break;
case 2:
break;
case 3:
role = "USER";
break;
//추가
case -1:
role = "Blocked";
break;
default:
role = "NONE";
break;
}
String result = null;
//추가
if("Blocked".equals(role)){
result = "커넥션 블로킹, 권한 정보 : "+role+ " / 접속시도 시간 : "+new Date().toString() ;
return result;
}
result = "커넥션 완료, 권한 정보 : " +role+ "/ 접속 시간 : "+new Date().toString() + "/ 사용 중인 스레드 : "+Thread.currentThread().getName();
return result;
}
}
//
public class Main {
public static void main(String[] args) throws UnsupportedEncodingException {
String encodedInfo = URLEncoder.encode("ADMIN&SOOMIN", "UTF-8");
DefaultProcessConnection defaultProcessConnection = new DefaultProcessConnection();
String result = defaultProcessConnection.requestConnection(encodedInfo);
System.out.println(result);
}
}
//로그
보안 작업 시작, 디코딩 할 String : ADMIN%26SOOMIN
인증 작업 시작 : Blocked / None
인가 결과 : -1
커넥션 블로킹, 권한 정보 : Blocked / 접속시도 시간 : Mon Nov 23 23:31:06 KST 2020
'Design Pattern' 카테고리의 다른 글
Prototype (0) | 2020.11.29 |
---|---|
SingleTon Pattern (0) | 2020.11.24 |
Factory Method (0) | 2020.11.24 |
Adapter (0) | 2020.11.23 |
Strategy (0) | 2020.11.23 |