基于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;
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧