从组合爆炸到优雅分派:复杂策略系统的工程化构建
干货分享,感谢您的阅读!在实际的工程系统中,我们经常遇到这样的场景:
- 推荐系统需要根据用户类型、内容标签、来源渠道、活动配置等组合选择不同策略;
- 风控系统需要根据地区、设备、交易类型、时间段来执行不同规则;
- 广告投放平台需要根据预算层级、素材类型、投放环境等参数自动选择出价逻辑。
这类问题的共同特点是:
维度多(组合爆炸)
策略多(共用与特例并存)
易变(新场景不断增加)
于是,大厂开始频繁地在面试中抛出类似的“策略组合分派系统设计题”,考察候选人的系统抽象能力、代码组织能力与工程可扩展性思维。
| 公司 | 常见题型方向 | 设计考察点 |
|---|---|---|
| 字节跳动(抖音、头条) | 推荐/广告策略系统;特征组合策略匹配 | 注解注册、组合分派、优先级策略 |
| 阿里巴巴(淘系、蚂蚁) | 营销/风控/规则引擎设计 | 规则抽象、DSL匹配、策略落地与容器化 |
| 腾讯(广告、视频号) | 用户画像 + 多维策略投放系统 | 策略复用与动态优先级 |
| 美团 | 配送调度策略 / 智能推荐规则 | 动态分派、参数维度建模 |
| 京东 | 价格策略 / 优惠券适配 / 库存调度 | 组合枚举 + 注解注册 + 策略路由 |
| 滴滴 / 高德 | 路线规划 / 费用策略 | 多维输入组合 + 最优策略选择 |
| Shopee / Lazada | 营销活动策略选择 | 国际化组合、规则解耦 |
当策略逻辑开始“乘法爆炸”,我们该如何在不崩溃的前提下,让系统依旧优雅?我在之前很早的博客中有讲解过简单的一些策略解法:
但是这种典型的 「策略组合 + 注解注册 + 策略分派」思维,基于粉丝求助,我想今天直接拿出来做一次博客分享:当策略逻辑开始“乘法爆炸”,我们该如何在不崩溃的前提下,让系统依旧优雅?
一、题目背景:复杂组合策略系统设计
在大型业务系统中,策略逻辑往往随着场景扩展而成倍增长。
例如,在推荐、活动、风控、广告、内容审核等系统中,不同的 用户类型(A)、渠道来源(B)、运行环境(C)、触发场景(D)共同决定了最终的策略选择。
如果我们使用多层 if-else 或硬编码去处理这些分支,不仅难以维护,还极易引发逻辑冲突与策略回退问题。
为此,我们希望设计一个:
基于多维组合 + 注解注册 + 动态分派 的策略系统。
二、系统要求与考察点
(一)基础要求
| 模块 | 说明 |
|---|---|
| A | 一级维度(2 种) |
| B | 二级维度(3 种) |
| C | 环境配置(2 种) |
| D | 场景触发(4 种) |
组合总数:2×3×2×4=48,我们需要支持:
为特定组合分配专属策略;
多组合共用一个策略;
默认兜底策略;
支持模糊匹配(如仅匹配 C、D);
自动注册、自动分派;
可扩展到 Spring 环境。
(二)设计考察点
| 维度 | 说明 |
|---|---|
| 架构抽象能力 | 策略接口 → 注册器 → 分派器,职责清晰 |
| 可扩展性 | 新增枚举或策略无需修改核心逻辑 |
| 冲突检测 | 当多个策略匹配时,选“最具体”策略 |
| 工程化能力 | 支持 Spring 扫描、Bean 装配、单元测试 |
| 通用性 | 可提炼成独立策略服务用于其他项目 |
三、核心架构设计
整个系统的设计可以类比为一个“策略中枢大脑”,当外部输入一组业务信息(A、B、C、D)时,它能自动找到最合适的策略实现并执行。
这套架构共分为 六个核心层次,每一层都承担着清晰的职责,层层解耦、自然协作
| 层级 | 职责 |
|---|---|
| 1️⃣ 枚举定义 | 定义 A/B/C/D 的取值 |
| 2️⃣ 组合类型 | 定义 Combination |
| 3️⃣ 策略接口 | 统一执行规范 |
| 4️⃣ 策略注解 | 通过 @StrategyFor 注册规则 |
| 5️⃣ 策略注册器 | 自动扫描并注册策略 |
| 6️⃣ 策略分派器 | 匹配最优策略并执行 |
我们可实现从“输入组合 → 自动选择策略 → 执行结果”的完整链路:

这一套架构的核心理念是:
用注解替代硬编码匹配,用分派器替代 if-else 嵌套。
通过“注册-匹配-执行”三步走,实现了一个可扩展、可热插拔的策略系统,新增策略时只需写一个新类 + 加一个注解,系统即可自动识别。
四、具体技术实现
(一)枚举与组合类设计
1. 具体枚举定义与实现
package org.zyf.javabasic.designpatterns.strategy.tiktok.base.enums;
/**
* @program: zyfboot-javabasic
* @description: 条件类型A
* @author: zhangyanfeng
* @create: 2025-11-02 15:23
**/
public enum AType {
A1, A2
}
package org.zyf.javabasic.designpatterns.strategy.tiktok.base.enums;
/**
* @program: zyfboot-javabasic
* @description: 条件类型B
* @author: zhangyanfeng
* @create: 2025-11-02 15:24
**/
public enum BType {
B1, B2, B3
}
package org.zyf.javabasic.designpatterns.strategy.tiktok.base.enums;
/**
* @program: zyfboot-javabasic
* @description: 条件类型C
* @author: zhangyanfeng
* @create: 2025-11-02 15:24
**/
public enum CType {
C1, C2
}
package org.zyf.javabasic.designpatterns.strategy.tiktok.base.enums;
/**
* @program: zyfboot-javabasic
* @description: 条件类型D
* @author: zhangyanfeng
* @create: 2025-11-02 15:24
**/
public enum DType {
D1, D2, D3, D4
}
2. 基本组合类定义
package org.zyf.javabasic.designpatterns.strategy.tiktok.base.types;
import org.zyf.javabasic.designpatterns.strategy.tiktok.base.enums.AType;
import org.zyf.javabasic.designpatterns.strategy.tiktok.base.enums.BType;
import org.zyf.javabasic.designpatterns.strategy.tiktok.base.enums.CType;
import org.zyf.javabasic.designpatterns.strategy.tiktok.base.enums.DType;
/**
* @program: zyfboot-javabasic
* @description: 枚举组合类
* @author: zhangyanfeng
* @create: 2025-11-02 15:29
**/
public class Combination {
private AType a;
private BType b;
private CType c;
private DType d;
public Combination(AType a, BType b, CType c, DType d) {
this.a = a;
this.b = b;
this.c = c;
this.d = d;
}
public AType getA() {
return a;
}
public BType getB() {
return b;
}
public CType getC() {
return c;
}
public DType getD() {
return d;
}
@Override
public String toString() {
return String.format("%s|%s|%s|%s", a, b, c, d);
}
}
(二)注解与策略接口
1. 基本注解设计
package org.zyf.javabasic.designpatterns.strategy.tiktok.base.strategy.annotation;
import org.zyf.javabasic.designpatterns.strategy.tiktok.base.enums.AType;
import org.zyf.javabasic.designpatterns.strategy.tiktok.base.enums.BType;
import org.zyf.javabasic.designpatterns.strategy.tiktok.base.enums.CType;
import org.zyf.javabasic.designpatterns.strategy.tiktok.base.enums.DType;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @program: zyfboot-javabasic
* @description: 注解策略接口
* @author: zhangyanfeng
* @create: 2025-11-02 18:23
**/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface StrategyFor {
AType[] a() default {};
BType[] b() default {};
CType[] c() default {};
DType[] d() default {};
}
2.基本策略接口设计
package org.zyf.javabasic.designpatterns.strategy.tiktok.base.strategy;
import org.zyf.javabasic.designpatterns.strategy.tiktok.base.types.Combination;
/**
* @program: zyfboot-javabasic
* @description: 策略接口
* @author: zhangyanfeng
* @create: 2025-11-02 18:25
**/
public interface Strategy {
void execute(Combination combination);
}
(三)示例策略实现
我们通过多个策略实现类来展示策略系统的声明与复用。每个策略类都通过 @StrategyFor 注解标明其适配的组合条件:
StrategyAlpha:覆盖A1+{B1,B2}+C1下的所有D情况;StrategyC2D4:专门处理C2且D4的组合,无视 A/B;DefaultStrategy:不限制任何条件,作为兜底策略。
设计目标实现“最小化重复”与“高可读性”的策略复用。
package org.zyf.javabasic.designpatterns.strategy.tiktok.base.strategy.impl;
import org.springframework.stereotype.Component;
import org.zyf.javabasic.designpatterns.strategy.tiktok.base.enums.AType;
import org.zyf.javabasic.designpatterns.strategy.tiktok.base.enums.BType;
import org.zyf.javabasic.designpatterns.strategy.tiktok.base.enums.CType;
import org.zyf.javabasic.designpatterns.strategy.tiktok.base.strategy.Strategy;
import org.zyf.javabasic.designpatterns.strategy.tiktok.base.strategy.annotation.StrategyFor;
import org.zyf.javabasic.designpatterns.strategy.tiktok.base.types.Combination;
/**
* @program: zyfboot-javabasic
* @description: 覆盖 A1 + {B1,B2} + C1 下的所有 D 情况;
* @author: zhangyanfeng
* @create: 2025-11-02 18:28
**/
@StrategyFor(a = {AType.A1}, b = {BType.B1, BType.B2}, c = {CType.C1})
@Component
public class StrategyAlpha implements Strategy {
@Override
public void execute(Combination combination) {
System.out.println("StrategyAlpha handling: " + combination);
}
}
package org.zyf.javabasic.designpatterns.strategy.tiktok.base.strategy.impl;
import org.springframework.stereotype.Component;
import org.zyf.javabasic.designpatterns.strategy.tiktok.base.enums.CType;
import org.zyf.javabasic.designpatterns.strategy.tiktok.base.enums.DType;
import org.zyf.javabasic.designpatterns.strategy.tiktok.base.strategy.Strategy;
import org.zyf.javabasic.designpatterns.strategy.tiktok.base.strategy.annotation.StrategyFor;
import org.zyf.javabasic.designpatterns.strategy.tiktok.base.types.Combination;
/**
* @program: zyfboot-javabasic
* @description: StrategyC2D4:专门处理 C2 且 D4 的组合,无视 A/B;
* @author: zhangyanfeng
* @create: 2025-11-02 18:32
**/
@StrategyFor(c = {CType.C2}, d = {DType.D4})
@Component
public class StrategyC2D4 implements Strategy {
@Override
public void execute(Combination combination) {
System.out.println("StrategyC2D4 handling: " + combination);
}
}
package org.zyf.javabasic.designpatterns.strategy.tiktok.base.strategy.impl;
import org.springframework.stereotype.Component;
import org.zyf.javabasic.designpatterns.strategy.tiktok.base.strategy.Strategy;
import org.zyf.javabasic.designpatterns.strategy.tiktok.base.strategy.annotation.StrategyFor;
import org.zyf.javabasic.designpatterns.strategy.tiktok.base.types.Combination;
/**
* @program: zyfboot-javabasic
* @description: 不限制任何条件,作为兜底策略。
* @author: zhangyanfeng
* @create: 2025-11-02 18:32
**/
@StrategyFor
@Component
public class DefaultStrategy implements Strategy {
@Override
public void execute(Combination combination) {
System.out.println("DefaultStrategy handling: " + combination);
}
}
说明:
- 可通过多个值覆盖多种组合;
未指定字段表示通配所有值;
默认策略作为兜底。
(四)策略注册器
StrategyRegistry 是连接“策略实现”和“策略分派”的桥梁,它让策略系统具备 自动化、可扩展、可维护 的工程化特性。具体代码如下:
package org.zyf.javabasic.designpatterns.strategy.tiktok.base.core.registry;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.zyf.javabasic.designpatterns.strategy.tiktok.base.strategy.Strategy;
import org.zyf.javabasic.designpatterns.strategy.tiktok.base.strategy.annotation.StrategyFor;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @program: zyfboot-javabasic
* @description: 策略注册器(核心组件)
*
* 【职责说明】
* 该组件在系统启动阶段自动扫描 Spring 容器中所有实现了 Strategy 接口的 Bean,
* 读取它们的 @StrategyFor 注解配置,并将“策略实例 + 匹配规则”注册到策略列表中。
* 后续由策略分派器(StrategyDispatcher)进行策略匹配与执行。
*
* 【设计目标】
* - 自动注册:免手工配置
* - 解耦扩展:策略定义与业务分离
* - 统一管理:集中维护策略元信息
*
* @author:
* @create: 2025-11-02 18:37
**/
@Component
public class StrategyRegistry implements ApplicationContextAware {
/** Spring 上下文,用于获取所有 Strategy Bean */
private ApplicationContext applicationContext;
/** 策略注册表,存放系统内所有策略信息 */
private final List strategies = new ArrayList<>();
/**
* 内部静态类,用于封装单个策略的注册信息:
* 包含策略对应的注解(匹配规则)与策略实例(执行对象)
*/
public static class RegisteredStrategy {
private final StrategyFor annotation;
private final Strategy instance;
public RegisteredStrategy(StrategyFor annotation, Strategy instance) {
this.annotation = annotation;
this.instance = instance;
}
public StrategyFor getAnnotation() {
return annotation;
}
public Strategy getInstance() {
return instance;
}
}
/**
* 容器启动后自动执行
*
* 1. 从 Spring 容器中获取所有实现 Strategy 接口的 Bean;
* 2. 判断是否标注了 @StrategyFor;
* 3. 如果是,则解析注解并注册到策略列表;
* 4. 最终打印所有已注册的策略信息。
*/
@PostConstruct
public void init() {
// 获取容器中所有 Strategy 类型的 Bean
Map beans = applicationContext.getBeansOfType(Strategy.class);
// 遍历所有策略 Bean,解析注解并注册
beans.values().forEach(strategy -> {
Class clazz = strategy.getClass();
if (clazz.isAnnotationPresent(StrategyFor.class)) {
StrategyFor annotation = clazz.getAnnotation(StrategyFor.class);
strategies.add(new RegisteredStrategy(annotation, strategy));
System.out.println("[StrategyRegistry] 注册策略: " + clazz.getSimpleName());
}
});
// 打印统计结果
System.out.println("[StrategyRegistry] 共注册策略数量: " + strategies.size());
}
/**
* 对外暴露所有注册策略
* 供分派器(StrategyDispatcher)使用
*/
public List getStrategies() {
return strategies;
}
/**
* 由 Spring 注入 ApplicationContext
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
StrategyRegistry 是策略组合系统的“信息中心”,它在整个架构中承担了 “策略收集器 + 注册中心” 的角色:
| 功能 | 说明 |
|---|---|
| 自动发现 | 系统启动后,自动扫描所有实现 Strategy 接口的策略类 |
| 注解解析 | 从每个策略类的 @StrategyFor 注解中提取匹配条件 |
| 集中注册 | 将策略实例与注解信息封装为 RegisteredStrategy 对象并缓存 |
| 提供查询 | 为分派器提供统一的策略清单,便于执行阶段快速定位策略 |
设计优势:
无需硬编码注册;
符合“开闭原则”(新增策略仅需新建类 + 注解);
可视化输出策略注册日志,方便排查;
轻量高效,适配生产级 Spring 应用。
(五)策略分派器
StrategyDispatcher 是策略系统的「调度核心」,它让策略体系从“静态 if-else 判断”进化为动态、可配置、可演化的智能分派系统。具体实现如下:
package org.zyf.javabasic.designpatterns.strategy.tiktok.base.core.dispatcher;
import org.springframework.stereotype.Component;
import org.zyf.javabasic.designpatterns.strategy.tiktok.base.core.registry.StrategyRegistry;
import org.zyf.javabasic.designpatterns.strategy.tiktok.base.strategy.Strategy;
import org.zyf.javabasic.designpatterns.strategy.tiktok.base.strategy.annotation.StrategyFor;
import org.zyf.javabasic.designpatterns.strategy.tiktok.base.types.Combination;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* @program: zyfboot-javabasic
* @description: 策略分派器(Strategy Dispatcher)
*
* 【职责说明】
* 该组件是整个策略系统的“大脑”,负责根据输入的组合(A/B/C/D)信息,
* 从注册中心中查找最匹配的策略实例,并将其分派执行。
*
* 【核心流程】
* 1️⃣ 从注册中心获取所有已注册策略;
* 2️⃣ 根据 @StrategyFor 注解规则过滤出匹配的策略;
* 3️⃣ 若存在多个匹配,按“具体度”(specificity)降序排序;
* 4️⃣ 返回最具体的策略;若无匹配,则回退到默认策略。
*
* 【特点】
* - 注解驱动、动态匹配
* - 自动优先选择“最具体”策略(即匹配条件最多者)
* - 可检测策略冲突(防止多个策略规则重复)
* - 支持默认策略兜底
*
* @author:
* @create: 2025-11-02 18:39
**/
@Component
public class StrategyDispatcher {
/** 策略注册中心,由 Spring 注入 */
private final StrategyRegistry registry;
public StrategyDispatcher(StrategyRegistry registry) {
this.registry = registry;
}
/**
* 分派策略:根据组合(Combination)匹配最合适的策略实现
*/
public Strategy dispatch(Combination combination) {
// 1️⃣ 获取所有匹配当前组合的策略
List matched = registry.getStrategies().stream()
.filter(rs -> matches(rs.getAnnotation(), combination))
.collect(Collectors.toList());
System.out.println("[StrategyDispatcher] 组合 " + combination + " 匹配策略数量: " + matched.size());
// 2️⃣ 无匹配策略则尝试默认策略
if (matched.isEmpty()) {
return findDefaultStrategy().orElseThrow(
() -> new RuntimeException("No matching strategy and no default strategy found for: " + combination)
);
}
// 打印匹配详情
matched.forEach(s -> System.out.println(" -> 匹配到: " + s.getInstance().getClass().getSimpleName()
+ " specificity=" + specificity(s.getAnnotation())));
// 3️⃣ 检查是否存在多个“等价”策略(即规则冲突)
if (matched.size() > 1) {
matched.sort(Comparator.comparingInt(
(StrategyRegistry.RegisteredStrategy rs) -> specificity(rs.getAnnotation())).reversed()
);
int top = specificity(matched.get(0).getAnnotation());
int next = specificity(matched.get(1).getAnnotation());
if (top == next) {
throw new IllegalStateException("存在策略冲突!匹配到多个等价策略: "
+ matched.stream()
.map(s -> s.getInstance().getClass().getSimpleName())
.collect(Collectors.joining(", ")));
}
}
// 4️⃣ 返回“最具体”的策略(规则约束最多者优先)
return matched.get(0).getInstance();
}
/**
* 判断注解定义的规则是否与当前组合匹配
* - 若注解未指定该维度(数组为空),视为“通配”
* - 若注解指定了,则必须完全匹配
*/
private boolean matches(StrategyFor anno, Combination c) {
if (anno == null || c == null) return false;
if (anno.a().length > 0 && Arrays.stream(anno.a()).noneMatch(x -> x == c.getA())) return false;
if (anno.b().length > 0 && Arrays.stream(anno.b()).noneMatch(x -> x == c.getB())) return false;
if (anno.c().length > 0 && Arrays.stream(anno.c()).noneMatch(x -> x == c.getC())) return false;
if (anno.d().length > 0 && Arrays.stream(anno.d()).noneMatch(x -> x == c.getD())) return false;
return true;
}
/**
* 计算策略“具体度”:
* 指定枚举值越多,代表策略越具体(优先级越高)
*/
private int specificity(StrategyFor anno) {
if (anno == null) return 0;
return (anno.a() == null ? 0 : anno.a().length)
+ (anno.b() == null ? 0 : anno.b().length)
+ (anno.c() == null ? 0 : anno.c().length)
+ (anno.d() == null ? 0 : anno.d().length);
}
/**
* 从注册中心中查找默认策略(DefaultStrategy)
* 实际项目中可改为通过注解或配置文件标识默认策略
*/
private Optional findDefaultStrategy() {
return registry.getStrategies().stream()
.map(StrategyRegistry.RegisteredStrategy::getInstance)
.filter(s -> s.getClass().getSimpleName().equals("DefaultStrategy"))
.findFirst();
}
}
StrategyDispatcher 是整个「策略组合系统」的核心控制器。它的职责就像调度中心,接收业务输入(A/B/C/D 组合),然后根据注册器提供的策略信息,智能地挑选出最合适的策略并执行。
| 功能点 | 说明 |
|---|---|
| 动态匹配 | 依据注解匹配当前组合条件 |
| 具体优先 | 指定条件越多的策略,优先级越高 |
| 冲突检测 | 多个策略规则重复时抛出异常 |
| 默认兜底 | 无匹配策略时自动启用 DefaultStrategy |
| 日志可观测 | 打印匹配过程、策略选择与具体度,便于调试 |
设计亮点:
实现了策略体系的“智能分派”;
支持多维度组合匹配;
保持策略扩展与分派逻辑解耦;
可通过注解灵活控制策略适配范围。
(六)启动测试与校验
通过 StrategyDispatcherSpringTest 集成测试方式验证策略分派器 StrategyDispatcher 的实际行为。模拟不同的业务组合(Combination),确保分派逻辑能够正确命中对应策略或回退默认策略。
package org.zyf.javabasic.designpatterns.strategy.tiktok.base.biz;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.zyf.javabasic.designpatterns.strategy.tiktok.base.core.dispatcher.StrategyDispatcher;
import org.zyf.javabasic.designpatterns.strategy.tiktok.base.enums.AType;
import org.zyf.javabasic.designpatterns.strategy.tiktok.base.enums.BType;
import org.zyf.javabasic.designpatterns.strategy.tiktok.base.enums.CType;
import org.zyf.javabasic.designpatterns.strategy.tiktok.base.enums.DType;
import org.zyf.javabasic.designpatterns.strategy.tiktok.base.strategy.Strategy;
import org.zyf.javabasic.designpatterns.strategy.tiktok.base.strategy.impl.DefaultStrategy;
import org.zyf.javabasic.designpatterns.strategy.tiktok.base.strategy.impl.StrategyAlpha;
import org.zyf.javabasic.designpatterns.strategy.tiktok.base.strategy.impl.StrategyC2D4;
import org.zyf.javabasic.designpatterns.strategy.tiktok.base.types.Combination;
import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.assertTrue;
/**
* @program: zyfboot-javabasic
* @description: 业务测试(SpringBootTest)
* @author: zhangyanfeng
* @create: 2025-11-02 19:54
**/
@RunWith(SpringRunner.class)
@SpringBootTest
public class StrategyDispatcherSpringTest {
@Autowired
private StrategyDispatcher dispatcher;
@Test
public void testAlphaMatch() {
Combination combo = new Combination(AType.A1, BType.B2, CType.C1, DType.D3);
Strategy strategy = dispatcher.dispatch(combo);
strategy.execute(combo);
assertTrue(strategy instanceof StrategyAlpha);
}
@Test
public void testC2D4Match() {
Combination combo = new Combination(AType.A2, BType.B3, CType.C2, DType.D4);
Strategy strategy = dispatcher.dispatch(combo);
strategy.execute(combo);
assertTrue(strategy instanceof StrategyC2D4);
}
@Test
public void testDefaultMatch() {
Combination combo = new Combination(AType.A2, BType.B3, CType.C1, DType.D2);
Strategy strategy = dispatcher.dispatch(combo);
strategy.execute(combo);
assertTrue(strategy instanceof DefaultStrategy);
}
@Test
public void testAll48Combinations() {
List results = new ArrayList<>();
// 遍历所有组合
for (AType a : AType.values()) {
for (BType b : BType.values()) {
for (CType c : CType.values()) {
for (DType d : DType.values()) {
// 构造组合对象
Combination combo = new org.zyf.javabasic.designpatterns.strategy.tiktok.base.types.Combination(a, b, c, d);
// 分派策略
Strategy strategy = dispatcher.dispatch(combo);
// 记录结果
String strategyName = strategy == null ? "null" : strategy.getClass().getSimpleName();
results.add(String.format("%s => %s", combo, strategyName));
}
}
}
}
// 输出结果
results.forEach(System.out::println);
// 简单验证默认策略是否存在
boolean defaultUsed = results.stream().anyMatch(r -> r.endsWith(DefaultStrategy.class.getSimpleName()));
assert defaultUsed : "至少有组合命中默认策略";
}
}
1. 测试目标与说明
| 测试方法 | 输入组合 | 期望命中策略 | 说明 |
|---|---|---|---|
testAlphaMatch() | (A1, B2, C1, D3) | StrategyAlpha | 验证多维度精确匹配策略分派是否正确 |
testC2D4Match() | (A2, B3, C2, D4) | StrategyC2D4 | 检查特定 C/D 组合策略的命中逻辑 |
testDefaultMatch() | (A2, B3, C1, D2) | DefaultStrategy | 测试无匹配场景下的默认策略回退机制 |
2. 验证说明
为了方便我们直接选取testAlphaMatch()说明如下:

五、总结:策略组合系统的魅力
面对用户类型、渠道、场景、环境这些多维组合,如果仍然依赖 if-else,代码很容易变成一团乱麻,逻辑一多就炸掉。而使用“组合 + 注解 + 分派器”的方式,我们把复杂逻辑抽象出来,系统可以自动根据输入选择最合适的策略,从而让复杂问题变得清晰可控。
新增策略也变得非常简单,只需写一个策略类,加上注解就能被系统识别,无需修改核心逻辑,也不用担心破坏已有功能。当多个策略匹配时,分派器会根据“具体度”自动判断优先级,同时检测策略冲突,避免重复或覆盖问题。而即便某个组合没有策略覆盖,默认策略也会顶上,保证系统不会出错。
更棒的是,这套系统经过了全面测试,可以遍历所有 48 种组合,确保每种情况都有对应策略,并且在匹配过程中打印日志,方便问题定位和调试。整个架构不仅适用于推荐、广告、风控等业务场景,还具有高度的复用性和可扩展性——即便未来新增维度或枚举值,核心逻辑几乎无需改动,系统自然就能支持。
用一句话总结就是:通过“组合 + 注解 + 分派器”,我们把复杂业务逻辑变得可维护、可扩展,而且更稳健,再也不用被策略乘法爆炸吓到。

浙公网安备 33010602011771号