[디자인 모델] --- 전략 모델 실전: 자바 에서 if - else 를 대체 하 는 큰 논리
43371 단어 디자인 모드
질문:
자바 는 원래 대상 을 대상 으로 하 는 언어 이지 만 많은 사람들 이 자바 가 대상 을 대상 으로 한다 고 말 한 다음 에 표 맵 실 체 를 제외 하고 다른 것 은 과정 을 대상 으로 하 는 사고 이다.예 를 들 어 오늘 말 하고 자 하 는 것 처럼 코드 의 큰 부분 인 if - else 판단 은 모든 if - else 코드 블록 에 복잡 한 논리 가 많아 서 전체 코드 가 혼 란 스 럽 고 다른 사람 이 보면 똥 같은 코드 를 보 는 것 처럼 느껴 집 니 다.
그렇다면 이 코드 들 을 어떻게 우아 하 게 대체 할 수 있 을 까? 사실은 디자인 모델 (전략 모델) 이 있 으 면 이 문 제 를 잘 해결 할 수 있다.
상황 예:
예 를 들 어 주문 처리, 주문 서 는 여러 type 상태 가 있 습 니 다. 예 를 들 어 type = 1 일 때 일반 주문 의 논 리 를 수행 합 니 다.type: 2 시 판 촉 주문 을 만 감 하 는 논 리 를 실행 합 니 다.type = 3 시 판 촉 주문 서 를 가득 채 우 는 논 리 를 실행 합 니 다.등등, type 은 수 십 가지, 심지어 더 많은 상황 이 있 을 수 있 습 니 다.
그리고 어떤 사람들 은 if - else 를 시작 합 니 다. 예 를 들 어 다음 과 같은 위조 코드 가 있 습 니 다.
if(type=1){
...( 100 )
}else if(type=2){
...( 100 )
}else if(type=3){
...( 100 )
}else if(type=n){
...( )
}
잘 하면 if - else 코드 블록 에서 의 논 리 를 하나씩 추출 하 는 방법 으로 약간 뚜렷 한 코드 가 있 지만 모두 과정 을 향 한 사상 입 니 다.나 는 이런 상황 은 다음 과 같은 방식, 즉 if - else 를 전략 모델 로 대체 하여 진정 으로 대상 을 대상 으로 해 야 한다 고 생각한다.각 유형의 주문 서 를 하나의 대상 으로 추출 한 다음 에 서로 다른 주해 표 지 를 통 해 호출 을 구분한다.
if - else 대신 정책 모드:
우선, 이번 사례 는 Spring - boot 프레임 을 사 용 했 으 며, 친 측 은 문제 가 없다.SpringMVC 프레임 도 괜 찮 을 거 예요.하나의 주문 클래스 를 정의 합 니 다. 그 안에 type 속성 이 있 습 니 다. type 은 '1', '2', '3' 일 수 있 습 니 다. 추상 적 인 추상 적 인 AbstractHandler 를 정의 합 니 다. 그 안에 추상 적 인 방법 handle 이 있 습 니 다. 가입 은 주문 클래스 에서 하나의 주해 Handler Type 을 정의 하고 하나의 value 속성 이 있 습 니 다. value 는 몇 가지 가 이 주해 의 이런 유형 을 대표 하 는 주문 정의 일반 클래스 Handler Impl 01 입 니 다.AbstractHandler 를 실현 하고 일반 주문, 즉 @ Handler Type ("1") 을 대표 합 니 다.일반 클래스 HandlerImpl 02 를 정의 하고 AbstractHandler 를 실현 하 며 판 촉 주문 서 를 만 감 하 는 것 을 대표 합 니 다. 즉, @ HandlerType ("2") 입 니 다.일반 클래스 HandlerImpl 03 을 정의 하고 AbstractHandler 를 실현 하 며 판 촉 주문 서 를 가득 채 우 는 것 을 대표 합 니 다. 즉, @ HandlerType ("3") 입 니 다.초기 화 클래스 HandlerProcessor 를 정의 하고 BeanFactory PostProcessor 를 실현 합 니 다. 과정 은 다음 과 같 습 니 다.서로 다른 type 에 대응 하 는 다른 종 류 를 저장 하기 위 한 것 이 분명 합 니 다.클래스 Handler Context 를 정의 합 니 다. handlerMap 이라는 맵 형식의 속성 이 있 습 니 다. getInstance 방법 이 있 습 니 다. 입력 은 type 이 고 AbstractHandler 로 돌아 갑 니 다.마지막 으로 사용 할 때 handler Context. getInstance 방법 을 호출 하여 type 에 따라 대응 하 는 Abstract Handler 를 가 져 옵 니 다.그리고 그의 handle 방법 을 호출 하여 주문 유형 에 대한 처리 논 리 를 실행 합 니 다.
구체 적 인 코드 는 다음 과 같다.
//@Data lombok , get/set
@Data
public class OrderDTO {
private String code;
private BigDecimal price;
/**
*
* 1:
* 2:
* 3:
*/
private String type;
}
public abstract class AbstractHandler {
abstract public String handle(OrderDTO orderDTO);
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface HandlerType {
String value();
}
@Component
@HandlerType("1")
public class HandlerImpl01 extends AbstractHandler {
@Override
public String handle(OrderDTO orderDTO) {
System.out.println(" type 1 ,orderDTO.type="+orderDTO.getType());
return "success";
}
}
@Component
@HandlerType("2")
public class HandlerImpl02 extends AbstractHandler {
@Override
public String handle(OrderDTO orderDTO) {
System.out.println(" type 2 ,orderDTO.type="+orderDTO.getType());
return "success";
}
}
@Component
@HandlerType("3")
public class HandlerImpl03 extends AbstractHandler {
@Override
public String handle(OrderDTO orderDTO) {
System.out.println(" type 3 ,orderDTO.type="+orderDTO.getType());
return "success";
}
}
@Component
@SuppressWarnings("unchecked")
public class HandlerProcessor implements BeanFactoryPostProcessor {
// handler ,
private static final String HANDLER_PACKAGE = "com.zs.handler";
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
Map<String, Class> handlerMap = new HashMap<>();
//
ClassScaner.scan(HANDLER_PACKAGE,HandlerType.class).forEach(clazz ->{
Annotation annotation = clazz.getAnnotation(HandlerType.class);
HandlerType handlerType = (HandlerType) annotation;
String type = handlerType.value();
System.out.println(type);
handlerMap.put(type,clazz);
});
HandlerContext handlerContext = new HandlerContext(handlerMap);
//
beanFactory.registerSingleton(HandlerContext.class.getName(),handlerContext);
}
}
public class HandlerContext {
private Map<String,Class> handlerMap;
public HandlerContext(Map<String, Class> handlerMap) {
this.handlerMap = handlerMap;
}
public AbstractHandler getInstance(String type){
Class clazz = handlerMap.get(type);
if(clazz == null){
throw new IllegalArgumentException(" type ,type:"+type);
}
return (AbstractHandler)SpringContextUtils.getBean(clazz);
}
}
정의 인터페이스:
public interface OrderService {
/**
*
* @param orderDTO
* @return
*/
String handle(OrderDTO orderDTO);
}
구현 인터페이스:
@Service
public class OrderServiceImpl implements OrderService {
@Resource
private HandlerContext handlerContext;
@Override
public String handle(OrderDTO orderDTO) {
System.out.println("OrderServiceImpl handle ===");
AbstractHandler handler = handlerContext.getInstance(orderDTO.getType());
return handler.handle(orderDTO);
}
}
패키지 스 캔 도구 종류:
public class ClassScaner implements ResourceLoaderAware {
private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
private final List<TypeFilter> includeFilters = new LinkedList<TypeFilter>();
private final List<TypeFilter> excludeFilters = new LinkedList<TypeFilter>();
private MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(this.resourcePatternResolver);
public ClassScaner() {
}
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
this.metadataReaderFactory = new CachingMetadataReaderFactory( resourceLoader);
}
// public final ResourceLoader getResourceLoader() {
// return this.resourcePatternResolver;
// }
public void addIncludeFilter(TypeFilter includeFilter) {
this.includeFilters.add(includeFilter);
}
// public void addExcludeFilter(TypeFilter excludeFilter) {
// this.excludeFilters.add(0, excludeFilter);
// }
// public void resetFilters(boolean useDefaultFilters) {
// this.includeFilters.clear();
// this.excludeFilters.clear();
// }
public static Set<Class> scan(String basePackage, Class<? extends Annotation>... annotations) {
ClassScaner cs = new ClassScaner();
for (Class anno : annotations)
cs.addIncludeFilter(new AnnotationTypeFilter(anno));
return cs.doScan(basePackage);
}
// public static Set scan(String[] basePackages, Class extends Annotation>... annotations) {
// ClassScaner cs = new ClassScaner();
// for (Class anno : annotations)
// cs.addIncludeFilter(new AnnotationTypeFilter(anno));
// Set classes = new HashSet();
// for (String s : basePackages)
// classes.addAll(cs.doScan(s));
// return classes;
// }
public Set<Class> doScan(String basePackage) {
Set<Class> classes = new HashSet<Class>();
try {
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
+ org.springframework.util.ClassUtils
.convertClassNameToResourcePath(SystemPropertyUtils
.resolvePlaceholders(basePackage))
+ "/**/*.class";
Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);
for (int i = 0; i < resources.length; i++) {
Resource resource = resources[i];
if (resource.isReadable()) {
MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);
if ((includeFilters.size() == 0 && excludeFilters.size() == 0)
|| matches(metadataReader)) {
try {
classes.add(Class.forName(metadataReader.getClassMetadata().getClassName()));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
} catch (IOException ex) {
throw new BeanDefinitionStoreException(
"I/O failure during classpath scanning", ex);
}
return classes;
}
protected boolean matches(MetadataReader metadataReader) throws IOException {
for (TypeFilter tf : this.excludeFilters) {
if (tf.match(metadataReader, this.metadataReaderFactory)) {
return false;
}
}
for (TypeFilter tf : this.includeFilters) {
if (tf.match(metadataReader, this.metadataReaderFactory)) {
return true;
}
}
return false;
}
}
spring 도구 클래스, bean 가 져 오기 위해
@Component
public class SpringContextUtils implements ApplicationContextAware {
private static ApplicationContext applicationContext = null;
public static ApplicationContext getApplicationContext(){
return applicationContext;
}
@SuppressWarnings("unchecked")
public static <T> T getBean(String beanId) {
return (T) applicationContext.getBean(beanId);
}
public static <T> T getBean(Class<T> requiredType) {
return (T) applicationContext.getBean(requiredType);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
SpringContextUtils.applicationContext = applicationContext;
}
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
디자인 모델 의 공장 모델, 단일 모델자바 는 23 가지 디자인 모델 (프로 그래 밍 사상/프로 그래 밍 방식) 이 있 습 니 다. 공장 모드 하나의 공장 류 를 만들어 같은 인 터 페 이 스 를 실현 한 일부 종 류 를 인 스 턴 스 로 만 드 는 것...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.