责任树模型
策略路由框架详解
这个目录包含了一个精心设计的策略路由框架,它是整个团购市场系统的核心设计模式基础。我将从接口到实现,详细讲解每个组件的功能和设计思想。
1. 整体架构概览
此框架采用了分层设计,从底层接口到高级抽象类,形成了一个完整的策略路由体系:
1
2
3
4
5
6
7
|
StrategyHandler (基础策略处理接口)
↑
StrategyMapper (策略映射器接口)
↑
AbstractStrategyRouter (基础策略路由抽象类)
↑
AbstractMultiThreadStrategyRouter (多线程策略路由抽象类)
|
2. 基础接口层
2.1 StrategyHandler<T, D, R>
- 策略处理器接口
这是整个框架的基石,定义了策略的核心执行方法:
1
2
3
4
|
public interface StrategyHandler<T, D, R> {
StrategyHandler DEFAULT = (T, D) -> null;
R apply(T requestParameter, D dynamicContext) throws Exception;
}
|
关键特性:
- 使用泛型
T
、D
、R
分别表示输入参数、动态上下文和返回结果
- 定义了默认实现
DEFAULT
,返回 null,用作兜底处理
apply
方法是策略执行的核心,接收请求参数和上下文,返回处理结果
2.2 StrategyMapper<T, D, R>
- 策略映射器接口
这个接口负责根据输入参数和上下文选择合适的策略处理器:
1
2
3
|
public interface StrategyMapper<T, D, R> {
StrategyHandler<T, D, R> get(T requestParameter, D dynamicContext) throws Exception;
}
|
关键特性:
get
方法是策略路由的核心,决定使用哪个策略处理器
- 通过分析输入参数和上下文,选择最适合的处理策略
- 设计为接口便于不同的路由算法实现
3. 抽象路由层
3.1 AbstractStrategyRouter<T, D, R>
- 基础策略路由器
这个抽象类将处理器和映射器结合起来,形成完整的路由功能:
1
2
3
4
5
6
7
8
9
10
11
12
|
public abstract class AbstractStrategyRouter<T, D, R>
implements StrategyMapper<T, D, R>, StrategyHandler<T, D, R> {
@Getter @Setter
protected StrategyHandler<T, D, R> defaultStrategyHandler = StrategyHandler.DEFAULT;
public R router(T requestParameter, D dynamicContext) throws Exception {
StrategyHandler<T, D, R> strategyHandler = get(requestParameter, dynamicContext);
if(null != strategyHandler) return strategyHandler.apply(requestParameter, dynamicContext);
return defaultStrategyHandler.apply(requestParameter, dynamicContext);
}
}
|
关键特性:
- 同时实现了
StrategyMapper
和 StrategyHandler
接口
- 提供
defaultStrategyHandler
作为兜底策略
- 提供
router
方法作为核心路由逻辑
- 先使用
get
方法获取处理器,再使用 apply
方法执行处理
3.2 AbstractMultiThreadStrategyRouter<T, D, R>
- 多线程策略路由器
这是对基础路由器的扩展,增加了异步数据加载能力:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
public abstract class AbstractMultiThreadStrategyRouter<T, D, R>
implements StrategyMapper<T, D, R>, StrategyHandler<T, D, R> {
// 同样拥有defaultStrategyHandler和router方法
@Override
public R apply(T requestParameter, D dynamicContext) throws Exception {
// 异步加载数据
multiThread(requestParameter, dynamicContext);
// 业务流程受理
return doApply(requestParameter, dynamicContext);
}
// 异步加载数据的抽象方法
protected abstract void multiThread(T requestParameter, D dynamicContext)
throws ExecutionException, InterruptedException, TimeoutException;
// 业务流程处理的抽象方法
protected abstract R doApply(T requestParameter, D dynamicContext) throws Exception;
}
|
关键特性:
- 覆盖了
apply
方法,增加异步数据加载步骤
- 将业务逻辑拆分为
multiThread
(异步加载数据)和 doApply
(业务处理)
- 适用于需要并行加载多个资源的复杂业务场景
- 支持异步编程模型,提高系统响应性
4. 设计思想和应用场景
4.1 设计思想
这个框架体现了多种高级设计思想:
- 泛型编程:使用泛型保证类型安全
- 组合优于继承:通过接口组合而非单纯继承实现功能扩展
- 模板方法模式:核心流程在抽象类中定义,具体步骤留给子类实现
- 策略模式:将不同的处理策略封装到不同的类中
- 责任链模式:通过路由机制构建处理链
- 异步编程模型:支持多线程并行处理提高性能
4.2 应用场景
这个框架特别适合以下场景:
- 复杂业务决策:需要根据多种因素选择处理路径
- 多级处理流程:业务流程有多个处理阶段,每个阶段有不同的处理逻辑
- 可扩展业务规则:需要频繁添加新的处理规则
- 高性能要求:需要并行加载多个资源以提高性能
- 树形决策结构:业务逻辑呈现树形结构的决策过程
5. 实际使用示例
在团购营销系统中,这个框架的使用方式:
- 创建具体的路由器(如
AbstractGroupBuyMarketSupport
)继承 AbstractStrategyRouter
- 实现
get
方法,根据产品类型和上下文选择合适的处理节点
- 实现
apply
方法,执行当前节点的业务逻辑
- 创建具体的处理节点(如
RootNode
、MarketNode
等)
- 使用工厂类
DefaultActivityStrategyFactory
初始化和管理节点
6. 框架的优势
- 高度解耦:每个策略的实现相互独立
- 易于扩展:添加新策略只需实现接口,不需修改现有代码
- 动态路由:根据运行时条件选择处理策略
- 异步支持:内置多线程异步处理能力
- 类型安全:泛型支持保证类型安全
- 兜底机制:提供默认处理器处理异常情况
7. 与经典设计模式的比较
- vs 传统策略模式:增加了动态路由选择,更适合复杂场景
- vs 责任链模式:增加了策略选择,更有结构化的处理方式
- vs 命令模式:增加了上下文传递,支持更复杂的业务状态
8. 性能考虑
- 异步处理:多线程版本支持并行加载数据
- 懒加载:策略可以按需创建和使用
- 路由缓存:可以在实现中添加路由结果缓存提高性能
总结
这个策略路由树框架是一个非常精巧的设计,它将策略模式和责任链模式的优点结合起来,再加上异步处理的能力,形成了一个功能强大、扩展性好的业务处理框架。在团购营销这样的复杂业务场景中,它能够有效地降低代码复杂度,提高系统的可维护性和可扩展性。
通过这种设计,业务逻辑可以被拆解为清晰的决策树,每个节点职责单一,便于理解和维护。而异步处理的支持则提高了系统的性能和响应能力。
策略路由树框架中的多线程实现详解
通过检索整个项目,我发现了策略路由树框架中多线程实现的全貌。这是一个精心设计的异步数据加载机制,用于提高系统性能和响应能力。下面是详细分析:
1. 多线程架构设计
1.1 核心抽象类 - AbstractMultiThreadStrategyRouter
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
public abstract class AbstractMultiThreadStrategyRouter<T, D, R> implements StrategyMapper<T, D, R>, StrategyHandler<T, D, R> {
@Override
public R apply(T requestParameter, D dynamicContext) throws Exception {
// 异步加载数据
multiThread(requestParameter, dynamicContext);
// 业务流程受理
return doApply(requestParameter, dynamicContext);
}
// 异步加载数据的抽象方法
protected abstract void multiThread(T requestParameter, D dynamicContext) throws ExecutionException, InterruptedException, TimeoutException;
// 业务流程处理的抽象方法
protected abstract R doApply(T requestParameter, D dynamicContext) throws Exception;
}
|
这个抽象类是多线程实现的核心,它:
- 覆盖了
apply
方法,将处理流程分为两个阶段
- 引入了
multiThread
抽象方法用于异步数据加载
- 引入了
doApply
抽象方法用于业务处理
- 确保数据加载完成后再进行业务处理
1.2 线程池配置 - ThreadPoolConfig
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
@Configuration
public class ThreadPoolConfig {
@Bean
public ThreadPoolExecutor threadPoolExecutor(ThreadPoolConfigProperties properties) {
// 创建线程池
return new ThreadPoolExecutor(
properties.getCorePoolSize(), // 核心线程数(默认20)
properties.getMaxPoolSize(), // 最大线程数(默认200)
properties.getKeepAliveTime(), // 空闲线程存活时间(默认10秒)
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(properties.getBlockQueueSize()), // 队列大小(默认5000)
Executors.defaultThreadFactory(),
handler); // 拒绝策略
}
}
|
项目使用了自定义的线程池配置,可通过外部参数调整:
- 核心线程数:20
- 最大线程数:200
- 线程存活时间:10 秒
- 队列大小:5000
- 可配置的拒绝策略
2. 多线程具体实现
2.1 线程任务封装
系统使用 Callable
接口封装具体的异步任务:
- 查询营销配置任务
1
2
3
4
5
6
7
8
9
10
|
public class QueryGroupBuyActivityDiscountVOThreadTask implements Callable<GroupBuyActivityDiscountVO> {
private final String source;
private final String channel;
private final IActivityRepository activityRepository;
@Override
public GroupBuyActivityDiscountVO call() throws Exception {
return activityRepository.queryGroupBuyActivityDiscountVO(source, channel);
}
}
|
- 查询商品信息任务
1
2
3
4
5
6
7
8
9
|
public class QuerySkuVOFromDBThreadTask implements Callable<SkuVO> {
private final String goodsId;
private final IActivityRepository activityRepository;
@Override
public SkuVO call() throws Exception {
return activityRepository.querySkuByGoodsId(goodsId);
}
}
|
2.2 异步任务执行 - MarketNode
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
public class MarketNode extends AbstractGroupBuyMarketSupport<MarketProductEntity, DefaultActivityStrategyFactory.DynamicContext, TrialBalanceEntity> {
@Resource
private ThreadPoolExecutor threadPoolExecutor;
@Override
protected void multiThread(MarketProductEntity requestParameter, DefaultActivityStrategyFactory.DynamicContext dynamicContext) throws ExecutionException, InterruptedException, TimeoutException {
// 异步查询活动配置
QueryGroupBuyActivityDiscountVOThreadTask task1 = new QueryGroupBuyActivityDiscountVOThreadTask(
requestParameter.getSource(), requestParameter.getChannel(), repository);
FutureTask<GroupBuyActivityDiscountVO> future1 = new FutureTask<>(task1);
threadPoolExecutor.execute(future1);
// 异步查询商品信息
QuerySkuVOFromDBThreadTask task2 = new QuerySkuVOFromDBThreadTask(
requestParameter.getGoodsId(), repository);
FutureTask<SkuVO> future2 = new FutureTask<>(task2);
threadPoolExecutor.execute(future2);
// 写入上下文 - 等待所有异步任务完成
dynamicContext.setGroupBuyActivityDiscountVO(future1.get(timeout, TimeUnit.MINUTES));
dynamicContext.setSkuVO(future2.get(timeout, TimeUnit.MINUTES));
}
@Override
public TrialBalanceEntity doApply(MarketProductEntity requestParameter, DefaultActivityStrategyFactory.DynamicContext dynamicContext) throws Exception {
// 使用异步加载的数据进行业务处理
// ...
return router(requestParameter, dynamicContext);
}
}
|
这是多线程实现的核心:
- 注入
ThreadPoolExecutor
线程池
- 在
multiThread
方法中创建并提交多个异步任务
- 使用
FutureTask
包装 Callable
任务
- 使用
future.get(timeout, TimeUnit)
等待任务完成,并设置超时时间
- 将异步获取的结果存入上下文
DynamicContext
- 在
doApply
方法中使用这些已加载的数据进行业务处理
2.3 上下文设计 - DynamicContext
1
2
3
4
5
6
7
8
9
10
|
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class DynamicContext {
// 拼团活动营销配置值对象
private GroupBuyActivityDiscountVO groupBuyActivityDiscountVO;
// 商品信息
private SkuVO skuVO;
}
|
上下文类用于存储异步获取的数据,供后续处理使用。
3. 多线程工作流程
整个多线程处理流程如下:
-
请求进入:外部请求调用 apply
方法
-
异步数据加载:
- 创建多个线程任务(查询活动配置、商品信息等)
- 提交到线程池并行执行
- 等待所有任务完成并获取结果
- 将结果存入上下文
-
业务处理:
- 异步数据加载完成后,执行
doApply
方法
- 使用上下文中的数据进行业务逻辑处理
- 继续路由到下一个节点(如 EndNode)
-
结果返回:返回最终处理结果
4. 多线程的优势
在这个设计中,多线程带来了几个关键优势:
- 性能提升:并行执行多个 IO 操作(如数据库查询),减少总体处理时间
- 资源优化:通过线程池管理,避免频繁创建和销毁线程
- 超时控制:设置任务超时时间,防止长时间阻塞
- 前置数据加载:提前并行加载多个节点可能需要的数据,提高系统响应性
- 业务解耦:数据加载与业务处理分离,使代码更清晰
5. 异常处理
多线程实现中的异常处理机制:
- 使用
try-catch
机制捕获异步任务中的异常
- 通过
Future.get()
抛出的异常传递给调用方
- 处理三种主要异常:
ExecutionException
:任务执行异常
InterruptedException
:线程中断异常
TimeoutException
:任务超时异常
总结
这个多线程实现是策略路由树框架的重要扩展,它通过并行数据加载优化了系统性能。核心思想是:将数据加载与业务处理分离,使用异步方式并行获取多个资源,然后在所有数据准备就绪后执行业务逻辑。
这种设计特别适合需要多个外部资源(数据库、外部服务等)的复杂业务场景,能够显著提高系统的响应性和吞吐量。同时,通过统一的抽象类和接口设计,使得异步逻辑能够无缝集成到现有的策略路由树框架中。