美文网首页设计模式
如何用Spring实现策略模式

如何用Spring实现策略模式

作者: 艺术类架构师 | 来源:发表于2019-06-13 17:10 被阅读0次

    引言

    在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改。这种类型的设计模式属于行为型模式。

    经典的商城打折生活用例,这种场景最适合用策略模式,客户将自己的身份告诉商城,商城根据客户的类型给予不同的优惠策略,普通用户不打折,会员8折,内部员工三折。如果不用设计模式用if...else语句实现起来也就几行代码的事情,不过这种实现方式看起来不太优雅,没有体现设计思维,所以我们尝试用Spring机制来实现策略模式吧。

    我们来看类图。

    image.png

    IDiscountStrategy是折扣接口

    *StrategyImpl这些类实现的是不同的客户类型使用的不同的折扣策略。

    StrateType是自定义折扣类型注解。

    StrategyHandlerComponent这个类是Spring的组件类,通过它获取所有的折扣类,将这些折扣类存放在一个线程安全的HashMap中,key存储的是DiscountEnum枚举中的name();
    一句话表达就是将折扣类和折扣类型关键字建立起mapping隐射。

    
    public enum  DiscountEnum {
    
      /**
       * 普通客户
       */
      NOMARL,
    
      /**
       * 会员
       */
      MEMBER,
    
    
      EMPLOYEE;
    }
    
    

    最后就是客户调用步骤

    @Autowired
        StrategyHandlerComponent strategyHandlerComponet;
    
        @GetMapping("/strategy")
        public String strategy(String strategy) {
            ConcurrentHashMap<String, IDiscountStrategy> map=strategyHandlerComponet.getDiscountStrategyConcurrentHashMap();
            if(map.keySet().contains(strategy)){
                return  "外星人不能享受折扣优惠";
            }
            return map.get(strategy).discount();
        }
    

    核心代码StrategyHandlerComponent

    package com.sgm.ossp.order.strategy;
    
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.BeanPostProcessor;
    import org.springframework.stereotype.Component;
    
    import java.util.concurrent.ConcurrentHashMap;
    
    @Component
    public class StrategyHandlerComponent implements  BeanPostProcessor {
    
        private ConcurrentHashMap<String,IDiscountStrategy> discountStrategyConcurrentHashMap=new ConcurrentHashMap<>();
    
        public ConcurrentHashMap<String, IDiscountStrategy> getDiscountStrategyConcurrentHashMap() {
            return discountStrategyConcurrentHashMap;
        }
    
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            Class aClass=bean.getClass();
            if(aClass.isAnnotationPresent(StrateType.class)&&isInstanceOfDiscountStrategy(aClass)){
                StrateType strateType= (StrateType) aClass.getAnnotation(StrateType.class);
                System.out.println("输出bean......"+bean.getClass().getName());
                discountStrategyConcurrentHashMap.put(strateType.value().name(),(IDiscountStrategy) bean);
            }
            return bean;
        }
    
    
        //类似于InitializingBean.afterPropertiesSet()
       //这里面获取所有的折扣实现类
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            return bean;
        }
    
        private boolean isInstanceOfDiscountStrategy( Class aClass){
            try {
                return  (aClass.newInstance() instanceof  IDiscountStrategy);
            } catch (Exception e) {
                return  false;
            }
        }
    
    
    }
    
    

    部署到Tomcat之后以get请求示例:{protocol}://{ip}:{port}/strategy?strategy={枚举类的name()}

    相关文章

      网友评论

        本文标题:如何用Spring实现策略模式

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