Spring优雅的实现策略模式

定义

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

算法结构 

  • 抽象策略角色(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;
    }
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个使用Spring框架实现策略模式的示例: 首先,定义一个策略接 `Strategy`,包含一个 `execute()` 方法: ```java public interface Strategy { void execute(); } ``` 然后,创建几个具体的策略类实现该接口: ```java @Component public class StrategyA implements Strategy { @Override public void execute() { System.out.println("执行策略A"); } } @Component public class StrategyB implements Strategy { @Override public void execute() { System.out.println("执行策略B"); } } @Component public class StrategyC implements Strategy { @Override public void execute() { System.out.println("执行策略C"); } } ``` 接下来,创建一个策略上下文类 `StrategyContext`,并使用Spring的依赖注入功能将所有的策略类注入进来: ```java @Component public class StrategyContext { private final Map<String, Strategy> strategyMap; public StrategyContext(List<Strategy> strategies) { this.strategyMap = strategies.stream().collect(Collectors.toMap(Strategy::getClass.getSimpleName, Function.identity())); } public void executeStrategy(String strategyName) { Strategy strategy = strategyMap.get(strategyName); if (strategy != null) { strategy.execute(); } else { throw new IllegalArgumentException("Unsupported strategy: " + strategyName); } } } ``` 最后,在其他需要使用策略模式的地方,可以通过依赖注入 `StrategyContext` 对象,并调用其 `executeStrategy()` 方法执行相应的策略: ```java @Component public class SomeService { private final StrategyContext strategyContext; public SomeService(StrategyContext strategyContext) { this.strategyContext = strategyContext; } public void doSomething(String strategyName) { strategyContext.executeStrategy(strategyName); } } ``` 这样,通过使用Spring框架的依赖注入功能,我们可以方便地在运行时动态切换不同的策略实现

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值