在实际开发工程中,常常会遇到多个ifelse的判断语句,对于简单的项目,还能够满足需求表。但是对于需求变更频繁的项目,这样会造成代码冗余同时且不易维护,不太建议采用这种方法。下面介绍一种springboot项目的解决方式。
1 基本代码
1.1service的接口代码
public interface OrderService {
String handle(OrderDTO orderDTO);
}
1.2 OrderDTO代码
public class OrderDTO {
private String code;
private BigDecimal price;
private String type;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
}
2两种实现方式
2.1传统方式
public String traditionalHandle(OrderDTO orderDTO){
String type = orderDTO.getType();
if ("1".equals(type)){
return "处理普通的类型";
}if ("2".equals(type)){
return "处理团购的类型";
}if ("2".equals(type)){
return "处理促销的类型";
}
return "错误处理";
}
2.2策略模式
@Autowired
private HandlerContext handlerContext;
@Override
public String handle(OrderDTO orderDTO) {
AbstractHandler handler = handlerContext.getInstance(orderDTO.getType());
return handler.handler(orderDTO);
}
3 策略+applicationContext容器方式
3.1实现思路
- 扫描对应的抽象类的多个实现类
- 将对应的实现类存储在hashMap容器中,并对外封装提供处理类
- 调用处理类完成业务需求
3.2代码实现
3.2.1HandlerProcessor
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
/**
* @author shuxibing
* @date 2019/7/31 15:03
* @uint d9lab
* @Description: 该类主要指将扫描的信息注入applicationContext容器中
*/
@Component
public class HandlerProcessor implements BeanFactoryPostProcessor {
/**
* 扫描hanglerMap注解兵注入容器中
* @param beanFactory
* @throws BeansException
*/
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
Map<String,Class> handlerMap=new HashMap<>(3);
ClassScaner.scan(Const.HANDLER_PACAGER,HandlerType.class).forEach(clazz->{
String type = clazz.getAnnotation(HandlerType.class).value();
handlerMap.put(type,clazz);
});
HandlerContext context=new HandlerContext(handlerMap);
beanFactory.registerSingleton(HandlerContext.class.getName(),context);
}
}
3.2.2 AbstractHandler 和实现类
public abstract class AbstractHandler {
public abstract String handler(OrderDTO orderDTO);
}
@Component
@HandlerType("1")
public class NormalHandler extends AbstractHandler {
@Override
public String handler(OrderDTO orderDTO) {
return "处理普通订单";
}
}
@Component
@HandlerType("2")
public class GroupHandler extends AbstractHandler {
@Override
public String handler(OrderDTO orderDTO) {
return "处理团购的类型";
}
}
@Component
@HandlerType("3")
public class PromotionHandler extends AbstractHandler {
@Override
public String handler(OrderDTO orderDTO) {
return "处理团购订单";
}
}
3.2.3 注解+扫描
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
public @interface HandlerType {
String value();
}
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternUtils;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.util.ClassUtils;
import org.springframework.util.SystemPropertyUtils;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.*;
/**
* @author shuxibing
* @date 2019/7/31 15:07
* @uint d9lab
* @Description:
*/
public class ClassScaner implements ResourceLoaderAware {
private final List<TypeFilter> includeFilters=new LinkedList<>();
private final List<TypeFilter> excludeFilters=new LinkedList<>();
private ResourcePatternResolver resourcePatternResolver=new PathMatchingResourcePatternResolver();
private MetadataReaderFactory metadataReaderFactory=new CachingMetadataReaderFactory(this.resourcePatternResolver);
public static Set<Class<?>> scan(String[] basepackages, Class<? extends Annotation>...annoations) {
ClassScaner cs=new ClassScaner();
//需要扫描的注解
if (ArrayUtils.isNotEmpty(annoations)){
for (Class anno:annoations){
cs.addIncludeFilter(new AnnotationTypeFilter(anno));
}
}
Set<Class<?>> classes=new HashSet<>();
for (String s:basepackages){
classes.addAll(cs.doScan(s));
}
return classes;
}
public static Set<Class<?>> scan(String basePackage,Class<? extends Annotation> ...annoations){
return scan(new String[]{basePackage},annoations);
}
private Set<Class<?>> doScan(String basePackage) {
Set<Class<?>> classes=new HashSet<>();
try {
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + ClassUtils.convertClassNameToResourcePath(SystemPropertyUtils.resolvePlaceholders(basePackage)) + "/**/*.class";
Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);
for (Resource resource : resources) {
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 e){
throw new BeanDefinitionStoreException("IO failure during classpath scanning",e);
}
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;
}
/**
* 设置解析器
* @param resourceLoader
*/
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourcePatternResolver= ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
this.metadataReaderFactory=new CachingMetadataReaderFactory(resourceLoader);
}
public void addIncludeFilter(TypeFilter typeFilter){
this.includeFilters.add(typeFilter);
}
public void addExcludeFilter(TypeFilter typeFilter){
this.excludeFilters.add(0,typeFilter);
}
public final ResourceLoader getResourceLoader(){
return this.resourcePatternResolver;
}
public void resetResourceLoader(){
this.includeFilters.clear();
this.excludeFilters.clear();
}
}
3.2.4 封装获取applicationContext的对象类
@Component
public class BeanTool implements ApplicationContextAware {
private static ApplicationContext applicationContext;
//自动初始化注入applicationContext
@Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
if (applicationContext==null){
applicationContext=context;
}
}
/**通过bean的缩写的方式获取类型
*
* @param name
* @return
*/
public static Object getBean(String name){
return applicationContext.getBean(name);
}
public static <T> T getBean(Class<T> clazz){
return applicationContext.getBean(clazz);
}
}
3.2.5 策略模式处理类
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);
}
return (AbstractHandler) BeanTool.getBean(clazz);
}
}
3.2.6 参数类
public class Const {
public static final String HANDLER_PACAGER="com.shu.example.strategymodel";
}