zoukankan      html  css  js  c++  java
  • SpringBoot中实现策略模式-减少if else

    ------------------------目录-------------------------------------

    一、策略模式概念

    二、策略模式优缺点

    三、借用springboot框架实现策略模式

    四、常见的实现策略模式

    ------------------------------------------------------------------

    一、策略模式概念

    策略(Strategy)模式的定义:该模式定义了一系列算法,并将每个算法封装起来,使它们可以相互替换,且算法的变化不会影响使用算法的客户。策略模式属于对象行为模式,它通过对算法进行封装,把使用算法的责任和算法的实现分割开来,并委派给不同的对象对这些算法进行管理。

    二、策略模式优缺点

    策略模式的主要优点如下

    1. 多重条件语句不易维护,而使用策略模式可以避免使用多重条件语句。
    2. 策略模式提供了一系列的可供重用的算法族,恰当使用继承可以把算法族的公共代码转移到父类里面,从而避免重复的代码。
    3. 策略模式可以提供相同行为的不同实现,客户可以根据不同时间或空间要求选择不同的。
    4. 策略模式提供了对开闭原则的完美支持,可以在不修改原代码的情况下,灵活增加新算法。
    5. 策略模式把算法的使用放到环境类中,而算法的实现移到具体策略类中,实现了二者的分离。

    其主要缺点如下:

    1. 客户端必须理解所有策略算法的区别,以便适时选择恰当的算法类。
    2. 策略模式造成很多的策略类。

    三、借用springboot框架实现策略模式

    1、简述

    由于公司开发一个类似IM通讯系统的项目,所以用到了大量的自定义事件,根据事件驱动进行业务处理。使用到了策略模式对于开发的团队成员来说只需要关注自己的业务实现即可,

    有统一的处理入口,自动路由。

    这里面有如下几个重要的类

      AbstractHandler:抽象类,定义业务处理方法和处理业务的类型。

      ContextHandlerService:对外暴露的类,根据参数类型进行业务路由。

      EventEnum、HandlerParam、HandlerResult:通用类分别对应:事件定义、请求通用参数、结果返回。

      业务实现类:继承AbstractHandler类重写方法。

    注:使用时候请注意ContextHandlerService类上的@Service和实现类上的@Componet注解,用于Spring扫描。

    项目结构

    2、源代码如下:

    AbstractHandler:抽象类。

    package city.ablert.commont;
    
    import java.util.List;
    
    /**
     * @author niunafei
     * @function
     * @email niunafei0315@163.com
     * @date 2020/7/29  4:06 PM
     */
    public abstract class AbstractHandler {
    
    
        /**
         * 业务处理实现抽象方法
         *
         * @param param
         * @return
         */
        public abstract HandlerResult strategy(HandlerParam param);
    
    
        /**
         * 返回业务类型,可以配置多个事件也可以是单个事件
         *
         * @return
         */
        public abstract List<EventEnum> eventTypes();
    }
    View Code

    ContextHandlerService:对外暴露的类。

    package city.ablert.service;
    
    import city.ablert.commont.AbstractHandler;
    import city.ablert.commont.EventEnum;
    import city.ablert.commont.HandlerParam;
    import city.ablert.commont.HandlerResult;
    import org.springframework.beans.BeansException;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    import org.springframework.stereotype.Service;
    
    import javax.annotation.PostConstruct;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * @author niunafei
     * @function
     * @email niunafei0315@163.com
     * @date 2020/7/29  4:13 PM
     */
    @Service
    public class ContextHandlerService implements ApplicationContextAware {
        private static final Map<EventEnum, AbstractHandler> HANDLER_MAP = new HashMap<>();
    
        private ApplicationContext applicationContext;
    
        /**
         * 实现ApplicationContextAware接口获取springboot容器对象
         * 方便创建完成对象后进行初始化
         *
         * @param applicationContext
         * @throws BeansException
         */
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            this.applicationContext = applicationContext;
        }
    
    
        /**
         * @PostConstruct 声明在创建完成对象并且注入属性后执行改方法
         *
         *
         */
        @PostConstruct
        public void init() {
            //获取AbstractHandler类的所有实现类
            Map<String, AbstractHandler> type = applicationContext.getBeansOfType(AbstractHandler.class);
            for (Map.Entry<String, AbstractHandler> entry : type.entrySet()) {
                //获取单个实现类
                AbstractHandler value = entry.getValue();
                if (value.eventTypes() == null) {
                    continue;
                }
                //或者注册事件,并且循环全部注册
                for (EventEnum eventEnum : value.eventTypes()) {
                    HANDLER_MAP.put(eventEnum, value);
                }
            }
        }
    
        /**
         * 业务处理类的路由方法
         * @param param
         * @return
         */
        public HandlerResult strategy(HandlerParam param) {
            AbstractHandler handler = HANDLER_MAP.get(param.getEvent());
            if (handler == null) {
                return null;
            }
            return handler.strategy(param);
        }
    }
    View Code

    EventEnum、HandlerParam、HandlerResult:事件定义、请求通用参数、结果返回。

    package city.ablert.commont;
    
    /**
     * @author niunafei
     * @function
     * @email niunafei0315@163.com
     * @date 2020/7/29  4:00 PM
     */
    public enum EventEnum {
        ERROR("error", "异常中断"),
        CLOSE("close", "正常关闭"),
        LOGIN("login", "登录"),
        HEALTHY("healthy", "健康监测");
    
        private String value;
    
        private String desc;
    
        EventEnum(String value, String desc) {
            this.value = value;
            this.desc = desc;
        }
    
        public String getValue() {
            return value;
        }
    
        public String getDesc() {
            return desc;
        }
    
        /**
         *
         * @param value
         * @return
         */
        public static EventEnum valueTo(String value) {
            EventEnum[] values = EventEnum.values();
            for (EventEnum anEnum : values) {
                if (anEnum.getValue().equals(value)) {
                    return anEnum;
                }
            }
            return null;
        }
    }
    View Code
    package city.ablert.commont;
    
    
    /**
     * @author niunafei
     * @function
     * @email niunafei0315@163.com
     * @date 2020/7/29  4:10 PM
     */
    public class HandlerParam<T> {
    
        public HandlerParam(EventEnum event) {
            this.event = event;
        }
    
        public HandlerParam(EventEnum event, T param) {
            this.event = event;
            this.param = param;
        }
    
        /**
         * 事件类型
         */
        private EventEnum event;
    
        /**
         * 请求业务参数泛型,对象
         */
        private T param;
    
    
        public EventEnum getEvent() {
            return event;
        }
    
        public void setEvent(EventEnum event) {
            this.event = event;
        }
    
        public T getParam() {
            return param;
        }
    
        public void setParam(T param) {
            this.param = param;
        }
    
        @Override
        public String toString() {
            return "HandlerParam{" +
                    "event=" + event +
                    ", param=" + param +
                    '}';
        }
    }
    View Code
    package city.ablert.commont;
    
    /**
     * @author niunafei
     * @function
     * @email niunafei0315@163.com
     * @date 2020/7/29  4:09 PM
     */
    public class HandlerResult<T> {
    
        /**
         * 构造方法
         */
        public HandlerResult() {
        }
    
        public HandlerResult(T result) {
            this.result = result;
        }
    
        /**
         * 返回结果泛型对象
         */
        private T result;
    
    
        public T getResult() {
            return result;
        }
    
        public void setResult(T result) {
            this.result = result;
        }
    
        @Override
        public String toString() {
            return "HandlerResult{" +
                    " result=" + result +
                    '}';
        }
    }
    View Code

    业务实现类:继承AbstractHandler类(拓展其他类型直接继承该类编写业务即可,调用统一的入口,需要指定事件类型)。

    package city.ablert.strategy;
    
    import city.ablert.commont.AbstractHandler;
    import city.ablert.commont.EventEnum;
    import city.ablert.commont.HandlerParam;
    import city.ablert.commont.HandlerResult;
    import org.springframework.stereotype.Component;
    
    import java.util.Arrays;
    import java.util.List;
    
    /**
     * @author niunafei
     * @function
     * @email niunafei0315@163.com
     * @date 2020/7/29  4:26 PM
     */
    @Component
    public class LoginHandler extends AbstractHandler {
    
        @Override
        public HandlerResult strategy(HandlerParam param) {
            //根据参数进行业务处理
            System.out.println("业务处理");
    
            //返回结果
            return new HandlerResult<String>("业务处理完毕");
        }
    
        @Override
        public List<EventEnum> eventTypes() {
            return Arrays.asList(EventEnum.LOGIN, EventEnum.HEALTHY);
        }
    }

    业务测试类

    package city.albert;
    
    import city.ablert.Application;
    import city.ablert.commont.EventEnum;
    import city.ablert.commont.HandlerParam;
    import city.ablert.commont.HandlerResult;
    import city.ablert.service.ContextHandlerService;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    
    /**
     * @author niunafei
     * @function
     * @email niunafei0315@163.com
     * @date 2020/7/29  4:42 PM
     */
    @SpringBootTest(classes = Application.class)
    @RunWith(SpringRunner.class)
    public class StrategyTest {
    
    
        @Autowired
        private ContextHandlerService service;
    
    
        @Test
        public void test() {
            //定于路由参数即可
            HandlerParam<String> param = new HandlerParam<>(EventEnum.LOGIN, "我是参数");
            System.out.println("请求参数:" + param);
            HandlerResult result = service.strategy(param);
            System.out.println("返回结果" + result);
    
        }
    }
    View Code

    运行结果

    四、常见的实现策略模式

    这里 ----> https://www.runoob.com/design-pattern/strategy-pattern.html

  • 相关阅读:
    转-iOS开发系列--地图与定位
    转-关于UIView的autoresizingMask属性的研究
    UIAlertController的使用,代替UIAlertView和UIActionSheet
    设置当前导航栏(navigationController)的标题
    tabBar隐藏方式
    ubuntu 安装qq 及解决安装完搜狗输入法不显示键盘的方法
    python 读写文件
    Ubuntu:如何显示系统托盘图标(systray)
    python tesseract 识别图片中的文字的乱码问题(ubuntu系统下)
    让Ubuntu可以压缩/解压缩RAR文件
  • 原文地址:https://www.cnblogs.com/niunafei/p/13398258.html
Copyright © 2011-2022 走看看