用策略模式处理不同订单的业务流程

策略模式的核心是要把频繁发生变化的部分封装起来,作用是把变化部分的影响隔离开,避免局部的变化对其它fixed部分造成影响,设计时可能需要更多的时间,但便于维护、复用与扩展(我的目的就是为了解决sql查出订单类型,不同的订单类型,走不同的处理流程)
代码下载地址:https://download.csdn.net/download/activety/12496580

VO类

@Data
public class OrderVo {

    /**
     * 订单id(自增主键)
     */
    private String id;
    /**
     * 总价
     */
    private BigDecimal  totalPrices;
    /**
     * 订单类型:
     * 1.普通订单 - "A"
     * 2.团促订单 - "B"
     * 3.促销订单 - "C"
     */
    private String type;

    //...省略若干
}

定义一个注解,value表示不同的策略

import java.lang.annotation.*;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface HandlerType {
    String value();
}

处理器上下文,根据类型获取相应的处理器

import java.util.Map;

@ResponseBody
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) {
            System.out.println("没有type为‘" + type + "’的处理器");
            throw new IllegalArgumentException("not found handler for type: " + type);

        }
        return (AbstractHandler) BeanTool.getBean(clazz);
    }
}

解析注解

@Component
public class HanlderProcessor implements BeanFactoryPostProcessor {

    private static final String HANDLER_PACKAGE="com.example.demo.handler";
    /**
     *  扫描@HandlerType,初始化HandlerContext,将其注册到spring容器
     * @param beanFactory bean工厂
     * @throws BeansException
     */
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        Map<String,Class> handlerMap = Maps.newHashMapWithExpectedSize(3);
        ClassScaner.scan(HANDLER_PACKAGE,HandlerType.class).forEach(clazz->{
            //获取注解中的类型值
            String type = clazz.getAnnotation(HandlerType.class).value();
            //将注解中的类型值作为key,对应的类作为value,保存在map中
            handlerMap.put(type,clazz);
        });
        HandlerContext context = new HandlerContext(handlerMap);
        beanFactory.registerSingleton(HandlerContext.class.getName(),context);
    }
}

工具类BeanTool

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public class BeanTool implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext context) throws BeansException {
        if (applicationContext == null) {
            applicationContext = context;
        }
    }

    public static Object getBean(String name) {
        return applicationContext.getBean(name);
    }

    public static <T> T getBean(Class<T> clazz) {
        return applicationContext.getBean(clazz);
    }
}

工具类ClassScaner

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.StringUtils;
import org.springframework.util.SystemPropertyUtils;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

/**
 * @Author: 李浩真
 * @Description:
 */
public class ClassScaner implements ResourceLoaderAware {

    private final List<TypeFilter> includeFilters = new LinkedList<TypeFilter>();
    private final List<TypeFilter> excludeFilters = new LinkedList<TypeFilter>();

    private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
    private MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(this.resourcePatternResolver);

    @SafeVarargs
    public static Set<Class<?>> scan(String[] basePackages, Class<? extends Annotation>... annotations) {
        ClassScaner cs = new ClassScaner();

        if (ArrayUtils.isNotEmpty(annotations)) {
            for (Class anno : annotations) {
                cs.addIncludeFilter(new AnnotationTypeFilter(anno));
            }
        }

        Set<Class<?>> classes = new HashSet<>();
        for (String s : basePackages) {
            classes.addAll(cs.doScan(s));
        }

        return classes;
    }

    @SafeVarargs
    public static Set<Class<?>> scan(String basePackages, Class<? extends Annotation>... annotations) {
        return ClassScaner.scan(StringUtils.tokenizeToStringArray(basePackages, ",; \t\n"), annotations);
    }

    public final ResourceLoader getResourceLoader() {
        return this.resourcePatternResolver;
    }

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourcePatternResolver = ResourcePatternUtils
                .getResourcePatternResolver(resourceLoader);
        this.metadataReaderFactory = new CachingMetadataReaderFactory(
                resourceLoader);
    }

    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 Set<Class<?>> doScan(String basePackage) {
        Set<Class<?>> classes = new HashSet<>();
        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;
    }
}

定义处理器
在这里插入图片描述

/**
*定义一个抽象法,通过重写该抽象方法实现不同的策略下的逻辑业务
*/
public abstract class AbstractHandler {
    public abstract String handler(OrderVo dto);
}
@Component
@HandlerType("A")
public class GroupHandler extends AbstractHandler {
    @Override
    public String handler(OrderVo orderVo) {
    	/**
         * 可以是具体的业务逻辑
         */
        System.out.println("对类型为 " + orderVo.getType() + " 的处理! ");
        return orderVo.getType();
    }
}
@Component
@HandlerType("B")
public class NormalHandler extends AbstractHandler {
    @Override
    public String handler(OrderVo orderVo) {
    	/**
         * 可以是具体的业务逻辑
         */
        System.out.println("对类型为 " + orderVo.getType() + " 的处理! ");
        return orderVo.getType();
    }
}
@Component
@HandlerType("C")
public class PromotionHandler extends AbstractHandler {
    @Override
    public String handler(OrderVo orderVo) {
   		 /**
         * 可以是具体的业务逻辑
         */
        System.out.println("对类型为 " + orderVo.getType() + " 的处理! ");
        return orderVo.getType();
    }
}

service接口:

public interface OrderService2 {
    /**
     * 根据不同的订单类型做不同的处理
     */
    String handler(OrderVo orderVo);
}

ServiceImpl

import com.example.demo.Vo.OrderVo;
import com.example.demo.handler.AbstractHandler;
import com.example.demo.annotation.HandlerContext;
import com.example.demo.service.OrderService2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class OrderServiceImpl2 implements OrderService2 {
    @Autowired(required = false)
    private HandlerContext handlerContext;
    @Override
    public String handler(OrderVo orderVo) {
        AbstractHandler handler = handlerContext.getInstance(orderVo.getType());
        return handler.handler(orderVo);
    }
}

Controller类

import com.example.demo.Vo.OrderVo;
import com.example.demo.service.OrderService2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class Contrroller {

    @Autowired
    private OrderService2 orderService2;
    
    /**
     * 使用策略模式
     * @param orderVo
     * @return
     */
    @RequestMapping("/test2")
    public String test2(OrderVo orderVo) {
        return orderService2.handler(orderVo);
    }

测试结果:在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值