美文网首页首页推荐JVM/Java
Spring优雅的实现策略模式

Spring优雅的实现策略模式

作者: 传达室马大爷 | 来源:发表于2018-09-26 11:01 被阅读103次

    源码

    https://github.com/shawntime/shawn-design-pattern/

    定义

    定义了一些平行的算法组,分别封装起来,算法之间可以相互替换,此模式使算法的变化独立于调用者之外

    算法结构

    • 抽象策略角色(Strategy):这是一个抽象类或者接口,将算法的行为进行封装,所有的策略类都要实现该接口
    • 具体策略角色(ConcreteStrategy):封装了具体的算法和行为
    • 环境角色(Context):持有一个抽象策略的引用,并提供统一调用的入口

    结构代码

    package com.shawntime.designpattern.strategy.demo;
    
    /**
     * 抽象策略类
     */
    public interface Strategy {
    
        // 策略方法
        void strategyInterface();
    }
    
    package com.shawntime.designpattern.strategy.demo;
    
    /**
     * Created by shma on 2018/9/26.
     */
    public class ConcreteStrategyA implements Strategy {
    
        public void strategyInterface() {
            // A相关业务
        }
    }
    
    package com.shawntime.designpattern.strategy.demo;
    
    /**
     * Created by shma on 2018/9/26.
     */
    public class ConcreteStrategyB implements Strategy {
    
        public void strategyInterface() {
            // B相关业务
        }
    }
    
    package com.shawntime.designpattern.strategy.demo;
    
    /**
     * 环境角色类
     */
    public class Context {
    
        private Strategy strategy;
    
        public Context(Strategy strategy) {
            this.strategy = strategy;
        }
    
        // 对外暴露的策略方法
        public void contextInterface() {
            strategy.strategyInterface();
        }
    
        public Strategy getStrategy() {
            return strategy;
        }
    
        public void setStrategy(Strategy strategy) {
            this.strategy = strategy;
        }
    }
    

    项目实例

    背景

    在项目中,根据专题id去获得该专题下活动的礼品信息, 由于每个专题活动礼品的方式不同,相互之间没有关联,属于平级的行为,因而采用策略模式。

    方案1:通过spring配置注入策略
    public interface IGiftInfoStrategyService {
    
        GiftInfo getGiftInfo(int activityId);
    }
    
    /**
     * 夏季购车节
     */
    @Service
    public class SummerBuyDayGiftInfoStrategyService implements IGiftInfoStrategyService {
    
        @Resource
        private GiftInfoMapper giftInfoMapper;
        
        public GiftInfo getGiftInfo(int activityId) {
            // 从数据库中查询
            GiftInfo giftInfo = new GiftInfo();
            giftInfo.setGiftId(1);
            giftInfo.setGiftName("铁锅三件套");
            giftInfoMapper.getGiftInfoByActivityId(activityId)
            return giftInfo;
        }
    }
    
    /**
     * 双11活动
     */
    @Service
    public class DoubleElevenGiftInfoStrategyService implements IGiftInfoStrategyService {
    
        @Override
        public GiftInfo getGiftInfo(int activityId) {
            // 双11调用统一平台接口获取礼品信息
            GiftInfo giftInfo = new GiftInfo();
            giftInfo.setGiftId(902);
            giftInfo.setGiftName("空气净化器");
            return giftInfo;
        }
    }
    
    /**
     * 礼品信息环境角色类
     */
    @Component
    public class GiftInfoContext {
    
        // 注入的策略
        @Autowired
        private Map<Integer, IGiftInfoStrategyService> giftInfoStrategyServiceMap;
    
        // 对外暴露的统一获取礼品信息的返回
        public GiftInfo getGiftInfo(int subjectId, int activityId) {
            IGiftInfoStrategyService giftInfoStrategyService = giftInfoStrategyServiceMap.get(subjectId);
            Assert.assertNotNull(giftInfoStrategyService);
            return giftInfoStrategyService.getGiftInfo(activityId);
        }
    }
    
    /**
     * 礼品信息配置类
     */
    @Configuration
    public class GiftInfoConfig {
    
        @Resource
        private IGiftInfoStrategyService doubleElevenGiftInfoStrategyService;
    
        @Resource
        private IGiftInfoStrategyService summerBuyDayGiftInfoStrategyService;
    
        /**
         * 注入bean
         */
        @Bean
        public Map<Integer, IGiftInfoStrategyService> giftInfoStrategyServiceMap() {
            Map<Integer, IGiftInfoStrategyService> dataMap = new HashMap<>();
            dataMap.put(1, summerBuyDayGiftInfoStrategyService);
            dataMap.put(2, doubleElevenGiftInfoStrategyService);
            return dataMap;
        }
    }
    
    /**
     * 礼品信息调用
     */
    public class GiftInfoTest {
    
        @Resource
        private GiftInfoContext giftInfoContext;
    
        public GiftInfo getGiftInfo(int subjectId, int activityId) {
            GiftInfo giftInfo = giftInfoContext.getGiftInfo(subjectId, activityId);
            Assert.assertNotNull(giftInfo);
            return giftInfo;
        }
    }
    
    方案2:通过静态方法配置
    public interface IGiftInfoStrategyService {
    
        GiftInfo getGiftInfo(int activityId);
    }
    
    /**
     * 双11活动
     */
    @Service
    public class DoubleElevenGiftInfoStrategyService implements IGiftInfoStrategyService {
    
        // 静态代码块中注册关联
        static {
            GiftInfoContext.registerProvider(2, DoubleElevenGiftInfoStrategyService.class);
        }
    
        @Override
        public GiftInfo getGiftInfo(int activityId) {
            // 双11调用统一平台接口获取礼品信息
            GiftInfo giftInfo = new GiftInfo();
            giftInfo.setGiftId(902);
            giftInfo.setGiftName("空气净化器");
            return giftInfo;
        }
    }
    
    /**
     * 夏季购车节
     */
    @Service
    public class SummerBuyDayGiftInfoStrategyService implements IGiftInfoStrategyService {
    
        // 静态代码块中注册关联
        static {
            GiftInfoContext.registerProvider(1, SummerBuyDayGiftInfoStrategyService.class);
        }
    
        @Resource
        private GiftInfoMapper giftInfoMapper;
        
        public GiftInfo getGiftInfo(int activityId) {
            // 从数据库中查询
            GiftInfo giftInfo = new GiftInfo();
            giftInfo.setGiftId(1);
            giftInfo.setGiftName("铁锅三件套");
            giftInfoMapper.getGiftInfoByActivityId(activityId)
            return giftInfo;
        }
    }
    
    /**
     * 礼品信息环境角色类
     */
    @Component
    public class GiftInfoContext {
    
        private static final Logger logger = LoggerFactory.getLogger(GiftInfoContext.class);
    
        // 策略映射map
        private static final Map<Integer, Class<?>> providers = new HashMap<>();
    
        // 提供给策略具体实现类的注册返回
        public static void registerProvider(int subjectId, Class<?> provider) {
            providers.put(subjectId, provider);
        }
    
        // 对外暴露的获取礼品信息接口返回
        public static GiftInfo getGiftInfo(int subjectId, int activityId) {
            Class<?> providerClazz = providers.get(subjectId);
            Assert.assertNotNull(providerClazz);
            Object bean = SpringUtils.getBean(providerClazz);
            Assert.assertNotNull(bean);
            if (bean instanceof IGiftInfoStrategyService) {
                IGiftInfoStrategyService strategyService = (IGiftInfoStrategyService) bean;
                return strategyService.getGiftInfo(activityId);
            }
            logger.error("Not Class with IGiftInfoListService: {}", providerClazz.getName());
            return null;
        }
    }
    
    public class GiftInfoTest {
    
        public GiftInfo getGiftInfo(int subjectId, int activityId) {
            GiftInfo giftInfo = GiftInfoContext.getGiftInfo(subjectId, activityId);
            Assert.assertNotNull(giftInfo);
            return giftInfo;
        }
    }
    
    方案3:通过spring自动注入list、map

    对于@Resource声明的数组、集合类型,spring并不是根据beanName去找容器中对应的bean,而是把容器中所有类型与集合(数组)中元素类型相同的bean构造出一个对应集合,注入到目标bean中

    public interface IGiftInfoStrategyService {
    
        GiftInfo getGiftInfo(int activityId);
         getTypeId();
    }
    
    /**
     * 夏季购车节
     */
    @Service
    public class SummerBuyDayGiftInfoStrategyService implements IGiftInfoStrategyService {
    
        @Resource
        private GiftInfoMapper giftInfoMapper;
        
        public GiftInfo getGiftInfo(int activityId) {
            // 从数据库中查询
            GiftInfo giftInfo = new GiftInfo();
            giftInfo.setGiftId(1);
            giftInfo.setGiftName("铁锅三件套");
            giftInfoMapper.getGiftInfoByActivityId(activityId)
            return giftInfo;
        }
    
         public int getTypeId() {
                return 1;
         }
    }
    
    /**
     * 双11活动
     */
    @Service
    public class DoubleElevenGiftInfoStrategyService implements IGiftInfoStrategyService {
    
        @Override
        public GiftInfo getGiftInfo(int activityId) {
            // 双11调用统一平台接口获取礼品信息
            GiftInfo giftInfo = new GiftInfo();
            giftInfo.setGiftId(902);
            giftInfo.setGiftName("空气净化器");
            return giftInfo;
        }
    
        public int getTypeId() {
                return 2;
         }
    }
    
    /**
     * 礼品信息环境角色类
     */
    @Component
    public class GiftInfoContext {
    
        // Spring自动注入
        @Resource
        private List<IGiftInfoStrategyService> giftInfoStrategyServiceList;
    
        // 对外暴露的统一获取礼品信息的返回
        public GiftInfo getGiftInfo(int subjectId, int activityId) {
              Optional<IGiftInfoStrategyService> optional = giftInfoStrategyServiceList.stream()
                                                      .filter(service -> service.getTypeId = subjectId)
                                                      .findFrist();
            if (!optional.isPresent()) {
                    Assert.assertNotNull(giftInfoStrategyService);
            }
      
            return optional.get().getGiftInfo(activityId);
        }
    }
    
    /**
     * 礼品信息配置类
     */
    @Configuration
    public class GiftInfoConfig {
    
        @Resource
        private IGiftInfoStrategyService doubleElevenGiftInfoStrategyService;
    
        @Resource
        private IGiftInfoStrategyService summerBuyDayGiftInfoStrategyService;
    
        /**
         * 注入bean
         */
        @Bean
        public Map<Integer, IGiftInfoStrategyService> giftInfoStrategyServiceMap() {
            Map<Integer, IGiftInfoStrategyService> dataMap = new HashMap<>();
            dataMap.put(1, summerBuyDayGiftInfoStrategyService);
            dataMap.put(2, doubleElevenGiftInfoStrategyService);
            return dataMap;
        }
    }
    
    /**
     * 礼品信息调用
     */
    public class GiftInfoTest {
    
        @Resource
        private GiftInfoContext giftInfoContext;
    
        public GiftInfo getGiftInfo(int subjectId, int activityId) {
            GiftInfo giftInfo = giftInfoContext.getGiftInfo(subjectId, activityId);
            Assert.assertNotNull(giftInfo);
            return giftInfo;
        }
    }
    

    相关文章

      网友评论

        本文标题:Spring优雅的实现策略模式

        本文链接:https://www.haomeiwen.com/subject/dexdoftx.html