1. 소개
이 기사에서는 널리 사용되는 행동 설계 패턴 인 책임 사슬에 대해 살펴보겠습니다 .
이전 기사 에서 더 많은 디자인 패턴을 찾을 수 있습니다 .
2. 책임의 사슬
Wikipedia 는 책임 사슬을 "명령 개체의 소스와 일련의 처리 개체"로 구성된 디자인 패턴으로 정의합니다.
체인의 각 처리 개체는 특정 유형의 명령을 담당하고 처리가 완료되면 명령을 체인의 다음 프로세서로 전달합니다.
책임 사슬 패턴은 다음에 유용합니다.
- 명령의 발신자와 수신자를 분리
- 처리 시간에 처리 전략 선택
패턴의 간단한 예를 살펴보겠습니다.
3. 예시
우리는 책임 사슬을 사용하여 인증 요청을 처리하기 위한 사슬을 만들 것입니다.
따라서 입력 인증 Provider는 명령 이 되고 각 인증 프로세서는 별도의 프로세서 개체가 됩니다.
먼저 프로세서에 대한 추상 기본 클래스를 생성해 보겠습니다.
public abstract class AuthenticationProcessor {
public AuthenticationProcessor nextProcessor;
// standard constructors
public abstract boolean isAuthorized(AuthenticationProvider authProvider);
}
다음으로 AuthenticationProcessor 를 확장하는 구체적인 프로세서를 만들어 보겠습니다 .
public class OAuthProcessor extends AuthenticationProcessor {
public OAuthProcessor(AuthenticationProcessor nextProcessor) {
super(nextProcessor);
}
@Override
public boolean isAuthorized(AuthenticationProvider authProvider) {
if (authProvider instanceof OAuthTokenProvider) {
return true;
} else if (nextProcessor != null) {
return nextProcessor.isAuthorized(authProvider);
}
return false;
}
}
public class UsernamePasswordProcessor extends AuthenticationProcessor {
public UsernamePasswordProcessor(AuthenticationProcessor nextProcessor) {
super(nextProcessor);
}
@Override
public boolean isAuthorized(AuthenticationProvider authProvider) {
if (authProvider instanceof UsernamePasswordProvider) {
return true;
} else if (nextProcessor != null) {
return nextProcessor.isAuthorized(authProvider);
}
return false;
}
}
여기에서 들어오는 권한 부여 요청에 대해 UsernamePasswordProcessor 및 OAuthProcessor라는 두 개의 구체적인 프로세서를 만들었습니다 .
각각에 대해 isAuthorized 메서드를 재정의했습니다.
이제 몇 가지 테스트를 만들어 보겠습니다.
public class ChainOfResponsibilityTest {
private static AuthenticationProcessor getChainOfAuthProcessor() {
AuthenticationProcessor oAuthProcessor = new OAuthProcessor(null);
return new UsernamePasswordProcessor(oAuthProcessor);
}
@Test
public void givenOAuthProvider_whenCheckingAuthorized_thenSuccess() {
AuthenticationProcessor authProcessorChain = getChainOfAuthProcessor();
assertTrue(authProcessorChain.isAuthorized(new OAuthTokenProvider()));
}
@Test
public void givenSamlProvider_whenCheckingAuthorized_thenSuccess() {
AuthenticationProcessor authProcessorChain = getChainOfAuthProcessor();
assertFalse(authProcessorChain.isAuthorized(new SamlTokenProvider()));
}
}
위의 예는 인증 프로세서 체인을 생성합니다: UsernamePasswordProcessor -> OAuthProcessor . 첫 번째 테스트에서는 인증이 성공하고 다른 테스트에서는 실패합니다.
먼저 UsernamePasswordProcessor 는 인증 Provider가 UsernamePasswordProvider 의 인스턴스인지 확인합니다 .
예상 입력이 아닌 UsernamePasswordProcessor 는 OAuthProcessor 에 Delegation합니다 .
마지막으로 OAuthProcessor 가 명령을 처리합니다. 첫 번째 테스트에서 일치 항목이 있고 테스트에 통과합니다. 두 번째는 체인에 더 이상 프로세서가 없기 때문에 테스트가 실패합니다.
4. 시행 원칙
책임 사슬을 구현하는 동안 몇 가지 중요한 원칙을 염두에 두어야 합니다.
- 체인의 각 프로세서에는 명령 처리를 위한 구현이 있습니다.
- 위의 예에서 모든 프로세서에는 isAuthorized 구현이 있습니다.
- 체인의 모든 프로세서는 다음 프로세서에 대한 참조를 가져야 합니다.
- 위에서 UsernamePasswordProcessor 는 OAuthProcessor 에 Delegation합니다 .
- 각 프로세서는 다음 프로세서에 Delegation할 책임이 있으므로 누락된 명령에 주의하십시오.
- 다시 이 예에서 명령이 SamlProvider 의 인스턴스인 경우 요청이 처리되지 않고 승인되지 않을 수 있습니다.
- 프로세서는 재귀 주기를 형성하면 안 됩니다.
- 이 예제에서는 체인에 주기가 없습니다: UsernamePasswordProcessor -> OAuthProcessor . 그러나 UsernamePasswordProcessor를 OAuthProcessor의 다음 프로세서로 명시적으로 설정하면 UsernamePasswordProcessor - > OAuthProcessor -> UsernamePasswordProcessor라는 체인의 주기로 끝납니다 . 생성자에서 다음 프로세서를 사용하면 도움이 될 수 있습니다.
- 체인에서 단 하나의 프로세서만이 주어진 명령을 처리합니다.
- 이 예에서 들어오는 명령에 OAuthTokenProvider 인스턴스가 포함되어 있으면 OAuthProcessor 만 명령을 처리합니다.
5. 실제 사용
Java 세계에서 우리는 매일 책임 사슬의 이점을 누리고 있습니다. 이러한 고전적인 예 중 하나는 여러 필터가 HTTP 요청을 처리할 수 있도록 하는 Java 의 서블릿 필터입니다. 이 경우 각 필터는 다음 필터 대신 체인을 호출합니다.
서블릿 필터에서 이 패턴을 더 잘 이해하기 위해 아래 코드 스니펫을 살펴보겠습니다 .
public class CustomFilter implements Filter {
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
// process the request
// pass the request (i.e. the command) along the filter chain
chain.doFilter(request, response);
}
}
위의 코드 조각에서 볼 수 있듯이 체인의 다음 프로세서에 요청을 전달하려면 FilterChain 의 doFilter 메서드를 호출해야 합니다.
6. 단점
이제 책임 사슬이 얼마나 흥미로운지 살펴보았으므로 몇 가지 단점을 염두에 두어야 합니다.
- 대부분 쉽게 깨질 수 있습니다.
- 프로세서가 다음 프로세서를 호출하지 못하면 명령이 삭제됩니다.
- 프로세서가 잘못된 프로세서를 호출하면 사이클이 발생할 수 있습니다.
- 성능에 영향을 줄 수 있는 깊은 스택 추적을 생성할 수 있습니다.
- 프로세서 간에 중복 코드가 발생하여 유지 관리가 증가할 수 있습니다.
7. 결론
이 기사에서는 들어오는 인증 요청을 승인하는 체인의 도움으로 책임 체인과 그 장단점에 대해 이야기했습니다.
그리고 항상 그렇듯이 소스 코드는 GitHub 에서 찾을 수 있습니다 .