zoukankan      html  css  js  c++  java
  • 【策略模式】策略模式结合Spring实战Demo

    策略模式

    策略模式用于解决判断分支过多的问题,使代码变得简洁和优雅,

    策略模式在多种方式在项目中落地,下面举例说明通过指定不同类型的订单使用策略模式执行不同的业务逻辑

    文章参考自公众号:石杉的架构笔记

    一.项目结构

     二.各个类的说明

      1.自定义注解

      //通过注解中的value值来表示不同的分支,从而执行不同的业务逻辑

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

      2.处理器相关

        -抽象处理器-定义子处理器要实现的行为

    public abstract class AbstractHandler {
    
        public  abstract String handle(OrderDTO dto);
    }

        -子处理器1-实现抽相关处理器的行为1

    @HandlerType(value = "1")
    @Component
    public class NomalHandler extends AbstractHandler{
        @Override
        public String handle(OrderDTO dto) {
            return "normal";
        }
    }

        -子处理器2-实现抽相关处理器的行为2

    @HandlerType(value = "2")
    @Component
    public class GroupHandler extends AbstractHandler{
        @Override
        public String handle(OrderDTO dto) {
            return "group";
        }
    }

        -处理器上下文-根据不同条件映射到不同的处理器

    public class HandleContext {
    
        private Map<String,Class> handlerMap;
    
        public HandleContext(Map<String,Class> handlerMap){
            this.handlerMap=handlerMap;
        }
    
        public AbstractHandler getInstance(String type){
            Class<? extends AbstractHandler> aClass = handlerMap.get(type);
            if (aClass==null) {
                throw new IllegalArgumentException();
            }
            return SpringContextUtil.getBean(aClass);
        }
    }

      3.处理器加载类-用于加载处理器上下文到spring的bean容器中,同时初始化数据

    @Component
    @SuppressWarnings("unchecked")
    public class HandlerProcessor implements BeanFactoryPostProcessor {
        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
            Map<String, Class> handlerMap = new HashMap<>();
            //获取指定报下的所有类
            ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
            MetadataReaderFactory metaReader = new CachingMetadataReaderFactory();
            List<Class<?>> list = new ArrayList();
            try {
                Resource[] resources = resolver.getResources("classpath*:designstrategy/demo/config/handler/*.class");
    
                ClassLoader loader = ClassLoader.getSystemClassLoader();
                for (Resource resource : resources) {
                    MetadataReader reader = metaReader.getMetadataReader(resource);
                    String className = reader.getClassMetadata().getClassName();
                    Class<?> clazz = loader.loadClass(className);
                    HandlerType annotation = clazz.getAnnotation(HandlerType.class);
                    // System.out.println("格式化前:"+clazz); class designstrategy.demo.config.handler.AbstractHandler
                    System.err.println("格式化后:" + ClassUtils.getQualifiedName(clazz));
                    //获取所有接口
                    ClassUtils.getAllInterfaces(clazz);
                    //判断是一个类是不是抽象类
                    boolean anAbstract = Modifier.isAbstract(clazz.getModifiers());
    //                System.err.println("判断一个类是不是抽象类:" + anAbstract);如果不是抽象类,添加到集合
                    if (!anAbstract) {
                        list.add(clazz);
                    }
                }
                System.out.println("集合" + list);
                //将类添加到Map中
                for (Class<?> aClass : list) {
                    Annotation[] annotations = aClass.getAnnotations();
    //              这里有个坑  Annotation annotation = aClass.getAnnotation(HandlerType.class);获取到的annotation为null
                    for (Annotation annotation : annotations) {
                        if (annotation instanceof HandlerType) {
                            String value = ((HandlerType) annotation).value();
                            handlerMap.put(value, aClass);
                            System.out.println(value);
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            HandleContext handleContext = new HandleContext(handlerMap);
            //将上下文添加到spring bean容器中
            configurableListableBeanFactory.registerSingleton(HandleContext.class.getName(), handleContext);
        }
    }

      4.工具类-用于获取spring 容器中的bean

    @Component
    public class SpringContextUtil implements ApplicationContextAware {
    
        private static ApplicationContext applicationContext;
    
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            SpringContextUtil.applicationContext = applicationContext;
        }
    
        //获取applicationContext
        public static ApplicationContext getApplicationContext() {
            return applicationContext;
        }
    
        //通过name获取 Bean.
        public static Object getBean(String name) {
            return getApplicationContext().getBean(name);
        }
    
        //通过class获取Bean.
        public static <T> T getBean(Class<T> clazz) {
            return getApplicationContext().getBean(clazz);
        }
    
        //通过name,以及Clazz返回指定的Bean
        public static <T> T getBean(String name, Class<T> clazz) {
            return getApplicationContext().getBean(name, clazz);
        }
    
    }

      5.controller层

    @RestController
    @RequestMapping("/order")
    public class OrderController {
    
    
        @Autowired
        private OrderService orderService;
    
        @RequestMapping("/handle")
        public String handle(OrderDTO dto){
            String str=orderService.handle(dto);
            System.out.println(str);
            return str;
        }
    }

      6.service层

    @Service
    public class OrderServiceImpl implements OrderService{
    
        @Autowired
        private HandleContext handleContext;
    
        @Override
        public String handle(OrderDTO dto) {
            AbstractHandler handler = handleContext.getInstance(dto.getType());
            return handler.handle(dto);
        }
    }

      7.实体 

    @Data
    public class OrderDTO {
        /** 订单类型 */
        private String type;
    }

    三.测试

    启动项目:使用postman分别测试以下两个接口

    接口一:localhost:8080/order/hander?type=1

    返回结果:normal

    接口二localhost:8080/order/hander?type=2

    返回结果:group

    代码地址:https://github.com/AlenYang123456/design-strategy

      

     

  • 相关阅读:
    分页插件加MVC
    在ASP.NET MVC中,有使用angularjs
    EF比较权威的一篇
    WEBFORM中添加bootstrap套件
    MVC统一设置命名空间
    重新生成索引及重新组织索引
    Dapper.Contrib.Extensions问题
    API Test WebApiTestClient工具安装及使用
    API Test Postman接口测试之高级篇2
    API Test Postman接口测试之高级篇1
  • 原文地址:https://www.cnblogs.com/july-sunny/p/11674639.html
Copyright © 2011-2022 走看看