基于SpringBoot框架实现策略设计模式

策略设计模式属于行为设计模式,这种模式可以使得程序在运行的时候,可以根据场景动态的选择适合的策略逻辑去执行,并且根据不同的需求可以去新增、修改不同的策略逻辑,具有极强的扩展性、可维护性

 

 

 


 

前几日面试,遇见这么一个业务场景:

 

饮品订单计价实现
饮品店有6种饮品出售:
  • 椰果奶茶:10元
  • 西米奶茶:10元
  • 蜂蜜奶茶:12元
  • 杏仁奶茶:14元
  • 美式咖啡:11元
  • 拿铁咖啡:12元
同时额外提供4种料可以添加:
  • 红豆:2元
  • 芋圆:2元
  • 奥利奥奶盖:4元
  • 芝士奶盖:5元
订单规则:
  • 一个订单最多包含10杯饮品
  • 每杯饮品每种料最多加一份
  • 咖啡只能加奶盖
  • 奥利奥奶盖和芝士奶盖不能同时添加
请实现订单计价程序:
  • 输入:订单内容,包括选择的饮品以及添加的料
  • 输出:订单总价格以及订单详情,订单详情包括买了哪些饮品,加了哪些料, 分别多少钱,非法订
  • 单直接输出-1
实现要求:
  • 自行定义输入、输出格式
  • 考虑饮品店后续可能的产品拓展
  • 提供可运行代码并且包含可运行的测试样例

 

看到题目后,思来想去,考虑到程序后续的扩展性,决定使用策略设计模式来实现。

 

大概思路:

构建一个Map<key,List<interface>>数据结构,key是类型,List<interface>是需要执行的策略,为什么是interface?因为利用java语言OOD的思想可以将interface的子类都存List中,为什么是集合?很明显一种类型可不只一种策略,所以这是一个List,这样的话,我们可以根据key去选择对应的策略集合去执行。关于数据结构的构建,可以利用SpringBoot中的BeanFactory获取。如果List很长的话,还可以设置一些优化的边界条件,比如超过5个或者10个可以使用CompletebleFutrue并行执行。也可以配置一些TAG对子类的class做过滤等等。

 

具体实现:

public interface BaseRule {
public void ruleHandler(OrderReq orderReq);
}
@Service
public class OrderRule implements BaseRule {
@Override
@RuleType(values = "*")
public void ruleHandler(OrderReq orderReq) {
//===============具体的校验逻辑==============
}
}
@Service
public class BeverageRule implements BaseRule {
@Override
@RuleType(values = "oreoMilklid")
    public void ruleHandler(OrderReq orderReq) {
//===============具体的校验逻辑==============
}
}
@Service
public class OrderRule implements BaseRule {

@Override
@RuleType(values = "*")
public void ruleHandler(OrderReq orderReq)
        //===============具体的校验逻辑==============
}
}


// 根据springboot的beanfactory获取注解下的所有子类,这样就得到了一个Map<key,interface>的数据结构,但是还要做一层处理转为Map<String,List<BaseRule>>
@Bean("ruleMaps")
public Map<String, List<BaseRule>> getSmsTradeTypeMapper() {
Map<String, BaseRule> baseRuleMap = applicationContext.getBeansOfType(BaseRule.class);
List<BaseRule> allTypeMatchList = new ArrayList<>();

Map<String,List<BaseRule>> ruleMaps = new HashMap<>();
baseRuleMap.entrySet().stream().forEach(o ->{
String className = o.getKey();
BaseRule baseRule = o.getValue();
Method[] methods = baseRule.getClass().getDeclaredMethods();
Arrays.stream(methods).forEach(k -> {
RuleType ruleType = k.getDeclaredAnnotation(RuleType.class);
if(ruleType != null){
String values = ruleType.values();
if(Constant.ALL_RULE.equals(values)){
allTypeMatchList.add(baseRule);
}else {
String[] types = values.split(",");
Arrays.stream(types).forEach(type ->{
List<BaseRule> baseRules = ruleMaps.get(type);
if(baseRules == null){
baseRules = new ArrayList<>();
}
baseRules.add(baseRule);
ruleMaps.put(type,baseRules);
});
}
ruleMaps.put("*",allTypeMatchList);
}
});

});
return ruleMaps;
}


// 具体的调用逻辑
public class RuleScheduler {

@Autowired
@Qualifier("ruleMaps")
private Map<String, List<BaseRule>> ruleMaps;

@Autowired
private ThreadPoolExecutor threadPoolExecutor;

public OrderReq filterOrder(OrderReq orderReq) throws ExecutionException, InterruptedException {
List<BaseRule> baseRules = ruleMaps.get(Constant.ALL_RULE);
List<CompletableFuture<OrderReq>> allRuleFutureList = new ArrayList<>(baseRules.size());
baseRules.stream().forEach(o ->{
CompletableFuture<OrderReq> completableFuture = CompletableFuture.supplyAsync(()->{
o.ruleHandler(orderReq);
return null;
}, threadPoolExecutor);
allRuleFutureList.add(completableFuture);
});
CompletableFuture<Void> allDoneFuture = CompletableFuture.allOf(allRuleFutureList.toArray(new CompletableFuture[allRuleFutureList.size()]));
CompletableFuture<List<OrderReq>> results = allDoneFuture
.thenApply(v -> allRuleFutureList.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList()));
List<OrderReq> orderReqs = getFutureResults(results);
Map<String, List<Beverage>> beverageMap = new HashMap<>();
List<Beverage> beverages = orderReq.getBeverages();
beverages.stream().forEach(o ->{
List<Beverage> bgs = beverageMap.get(o.getProductName());
if(CollectionUtils.isEmpty(beverageMap)){
bgs = new ArrayList<>();
}
bgs.add(o);
beverageMap.put(o.getProductName(),bgs);
});
beverageMap.entrySet().stream().forEach(o ->{
String productName = o.getKey();
List<BaseRule> productNameRules = ruleMaps.get(productName);
productNameRules.stream().forEach(ruleClass -> {
ruleClass.ruleHandler(orderReq);
});
});
return orderReq;
}
private static List<OrderReq> getFutureResults(CompletableFuture<List<OrderReq>> results) throws InterruptedException, ExecutionException {
List<OrderReq> tempResults = null;
try {
tempResults = results.get();
} catch (InterruptedException e) {
log.info("InterruptedException: {}", e.getMessage());
throw e;
} catch (ExecutionException e) {
log.info("ExecutionException: {}", e.getMessage());
throw e;
}
return tempResults;
}
}

  

 

posted @   cs7  阅读(275)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
点击右上角即可分享
微信分享提示