Spring Boot: 전략 디자인 패턴 - 편의성과 한계
11007 단어 javaspringboot
예를 들어 인터페이스를 정의하기만 하면 됩니다(명확성을 위해 이 예제에서만 접두사
I
를 사용함).public interface IOneStrategy {
void executeTheThing();
}
다음과 같이 일부 구현을 정의합니다.
@Service("FIRST")
public class OneStrategyFirst implements IOneStrategy {
@Override
public void executeTheThing() {
System.out.println("OneStrategyFirst.executeTheThing");
}
}
이제 다음과 같이 보이는 주어진 이름을 기반으로 적절한 전략을 실행하는 서비스를 간단히 구현할 수 있습니다.
@Service
public class ExecuteStrategyOne {
private Map<String, IOneStrategy> strategies;
public ExecuteStrategyOne(Map<String, IOneStrategy> strategies) {
this.strategies = strategies;
}
public void executeStrategyOne(String name) {
if (!strategies.containsKey(name)) {
throw new IllegalArgumentException("The strategy " + name + " does not exist.");
}
strategies.get(name).executeTheThing();
}
}
실제 세계에서는
OneStrategyFirst
, OneStrategySecond
및 OneStrategyThird
와 같은 전략 인터페이스의 여러 구현을 만듭니다. 때때로 사용법은 다른 구현이 필요한 REST API 또는 기타 도메인 특정 코드에서 제공하는 executeStrategyOne
매개변수를 사용하는 것입니다.여기서 편리함은 Spring Boot(더 정확하게는 Spring Framework)가 생성자를 통해
strategies
내의 ExecuteStrategyOne
맵에 다른 구현을 주입하는 것을 처리한다는 것입니다. 결과적으로 키가 @Service("FIRST")
에 의해 제공되는 값이고 맵의 값이 찾을 수 있는 인터페이스IOneStrategy
의 모든 구현에 대한 인스턴스화 클래스를 포함하는 맵이 생성됩니다.정말 편리합니다.
실생활에서 예제의
FIRST
, SECOND
및 THIRD
와 동일한 키를 사용하는 다른 전략이 필요합니까? 다음을 정의합시다.@Service("FIRST")
public class TwoStrategyFirst implements ITwoStrategy {
@Override
public void executeTheThing() {
System.out.println("TwoStrategyFirst.executeTheThing");
}
}
해당 Spring Boot 애플리케이션을 시작하려고 하면 다음과 같은 예외가 표시됩니다.
Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException:
Annotation-specified bean name 'FIRST' for bean class [com.soebes.examples.strategies.functions.two.TwoStrategyFirst]
conflicts with existing, non-compatible bean definition of same name and class
[com.soebes.examples.strategies.functions.one.OneStrategyFirst]
at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.checkCandidate(ClassPathBeanDefinitionScanner.java:349) ~[spring-context-5.2.9.RELEASE.jar:5.2.9.RELEASE]
at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:287) ~[spring-context-5.2.9.RELEASE.jar:5.2.9.RELEASE]
그렇다면 여기서 Spring Boot가 우리에게 제공하는 많은 편의를 잃지 않고 문제를 해결하기 위해 우리는 무엇을 할 수 있습니까?
먼저 각 전략 구현 클래스에서 다음과 같은 주석을 정의해야 합니다.
@Service
@Qualifier("FIRST")
public class TwoStrategyFirst implements ITwoStrategy {
@Override
public void executeTheThing() {
System.out.println("TwoStrategyFirst.executeTheThing");
}
}
다른 주석의 키를 사용하여 모순된 빈 이름의 중복을 방지하여 대신 사용합니다
@Service("FIRST")
. @Qualifier("FIRST")
의 사용법은 우리에게 다른 것을 처리하는 기준을 제공합니다.이제 다음과 같이
ExecuteStrategyOne
클래스를 변경해야 합니다.@Service
public class ExecuteStrategyOne {
private Map<String, IOneStrategy> strategies;
public ExecuteStrategyOne(List<IOneStrategy> strategies) {
this.strategies = strategies.stream()
.collect(
toMap(k -> k.getClass().getDeclaredAnnotation(Qualifier.class).value(),
Function.identity()));
}
...
}
이전에 사용된
List<IOneStrategy> strategies
대신 생성자 매개변수Map<String, IOneStrategy> strategies
의 사용을 강조하고 싶습니다. 이는 주어진 인터페이스에서 Spring Boot에 의해 해당 목록으로 모든 구현 목록을 가져오는 데 편리합니다. 이제 @Qualifier
주석을 사용하여 정의한 키로 맵으로 변환해야 합니다. 다음과 같은 스트림으로 모든 것을 해결할 수 있습니다.this.strategies = strategies
.stream()
.collect(
Collectors.toMap(k -> k.getClass().getDeclaredAnnotation(Qualifier.class).value(),
Function.identity()));
구현을 살펴보고 주석
@Qualifier
을 추출하고 갖고 싶은 키value()
를 읽습니다. Collectors.toMap
를 사용하여 결과를 Map에 수집하고 그 결과를 인스턴스 변수private Map<String, IOneStrategy> strategies;
에 할당합니다.필요에 따라 인스턴스 변수를
final
로 정의하는 것이 물론 가능하며 필요한 경우 Collectors.toUnmodifiableMap
대신 적절한 toMap(..)
를 사용하여 수정할 수 없는 맵을 만들 수 있습니다.따라서 코드를 약간 변경하면 코드에서 동일한 키를 사용하는 다른 전략을 사용하는 문제를 쉽게 해결할 수 있습니다.
주어진 코드는 full working example on GitHub 으로 사용할 수 있습니다.
Reference
이 문제에 관하여(Spring Boot: 전략 디자인 패턴 - 편의성과 한계), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/khmarbaise/spring-boot-strategy-design-pattern-convenience-and-limitation-2mee텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)