Spring优雅的实现策略模式

源码

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 {

    // 注入的策略
    @Resource
    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;
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值