Files
ruoyi-vue-pro/.claude/skills/usage/pattern-usage.md

1341 lines
44 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
# Skills 自动引用配置
# AI 读取本文档时会自动加载以下规范文件,确保生成的代码符合项目规范
references:
patterns:
- path: skills/patterns/factory-pattern.yaml
reason: "工厂模式 - 对象创建的统一管理"
- path: skills/patterns/strategy-pattern.yaml
reason: "策略模式 - 算法族的统一接口"
- path: skills/patterns/template-method-pattern.yaml
reason: "模板方法模式 - 算法骨架的固定结构"
reference_modules:
- path: skills/modules/pay/skill-pay.yaml
reason: "支付模块 - 工厂+策略+模板方法模式组合案例"
- path: skills/modules/ai/skill-ai.yaml
reason: "AI 模块 - 工厂+策略模式案例"
- path: skills/modules/infra/skill-infra.yaml
reason: "基础设施模块 - 文件存储策略模式案例"
usage_hint: "设计模式通常组合使用,参考 pay 模块的完整案例"
---
# 设计模式应用场景提示词指南
> 本文档提供设计模式应用的标准化提示词模板,帮助开发者快速选择和应用合适的设计模式。
---
## 目录
1. [设计模式选择指南](#1-设计模式选择指南)
2. [工厂模式应用提示词](#2-工厂模式应用提示词)
3. [策略模式应用提示词](#3-策略模式应用提示词)
4. [模板方法模式应用提示词](#4-模板方法模式应用提示词)
5. [实际案例分析](#5-实际案例分析)
6. [模式组合使用](#6-模式组合使用)
---
## 1. 设计模式选择指南
### 1.1 场景-模式映射表
| 场景描述 | 推荐模式 | 项目案例 |
|---------|---------|---------|
| 需要根据配置动态创建不同类型的客户端 | 工厂模式 + 策略模式 | 支付渠道、短信渠道、文件存储 |
| 需要统一处理流程,但具体实现不同 | 模板方法模式 | 支付下单流程、短信发送流程 |
| 需要动态切换算法或行为 | 策略模式 | AI模型切换、支付方式切换 |
| 需要隔离第三方SDK差异 | 策略模式 + 工厂模式 | 支付SDK、AI模型SDK |
| 需要支持扩展新的产品类型 | 工厂模式 | 新增支付渠道、新增存储类型 |
| 需要管理多个同类对象实例 | 工厂模式(带缓存) | PayClientFactory缓存客户端 |
### 1.2 选择决策树
```
需要解决的问题是什么?
|
+-- 创建对象
| |
| +-- 创建逻辑复杂,需要封装 --> 工厂模式
| +-- 需要根据类型动态创建 --> 工厂模式
| +-- 需要缓存和复用实例 --> 工厂模式(带缓存)
|
+-- 行为变化
| |
| +-- 需要动态切换算法 --> 策略模式
| +-- 有多种可互换的实现 --> 策略模式
| +-- 需要统一流程框架 --> 模板方法模式
|
+-- 组合场景
|
+-- 创建 + 行为变化 --> 工厂模式 + 策略模式
+-- 统一流程 + 具体实现不同 --> 工厂模式 + 模板方法模式
+-- 完整的多渠道系统 --> 工厂 + 策略 + 模板方法
```
### 1.3 模式特性对比
| 特性 | 工厂模式 | 策略模式 | 模板方法模式 |
|-----|---------|---------|-------------|
| 类型 | 创建型 | 行为型 | 行为型 |
| 主要目的 | 封装对象创建 | 封装可互换算法 | 定义算法骨架 |
| 开闭原则 | 支持 | 支持 | 支持 |
| 扩展方式 | 新增工厂方法 | 新增策略类 | 新增子类 |
| 客户端感知 | 不感知具体类 | 需选择策略 | 不感知实现细节 |
| 适用场景 | 多类型创建 | 算法切换 | 流程标准化 |
---
## 2. 工厂模式应用提示词
### 2.1 标准提示词模板
```markdown
## 任务:使用工厂模式设计 [系统名称]
### 业务背景
[描述业务场景,例如:需要支持多种支付渠道,包括微信支付、支付宝、银联等]
### 设计要求
1. 创建抽象产品接口
- 定义 [产品名称] 接口
- 包含以下核心方法:
- [方法1][功能描述]
- [方法2][功能描述]
2. 创建具体产品实现
- 为每种类型创建实现类
- 实现类命名规范:[类型][产品]Impl如 AlipayPayClient
3. 创建工厂类
- 工厂命名:[产品]Factory如 PayClientFactory
- 提供创建方法create[产品](配置参数)
- 考虑是否需要缓存实例
4. 注册机制
- 使用 Map 存储类型与实现类的映射
- 支持动态注册新类型
### 参考实现
参考项目中 PayClientFactory 的实现模式。
```
### 2.2 工厂模式提示词示例:多渠道短信系统
```markdown
## 任务:使用工厂模式设计短信客户端工厂
### 业务背景
系统需要支持多种短信渠道:阿里云短信、腾讯云短信、华为云短信、七牛云短信。
不同渠道有不同的SDK和配置但对外需要提供统一的发送接口。
### 设计要求
#### Step 1: 创建短信客户端接口
```java
public interface SmsClient {
Long getId();
void init();
SmsSendResultDTO sendSms(SmsSendMessageDTO message);
SmsTemplateRespDTO getTemplate(String templateId);
}
```
#### Step 2: 创建配置接口
```java
public interface SmsClientConfig {
void validate();
}
```
#### Step 3: 创建抽象基类(可选,结合模板方法)
```java
public abstract class AbstractSmsClient implements SmsClient {
protected Long id;
protected SmsClientConfig config;
public AbstractSmsClient(Long id, SmsClientConfig config) {
this.id = id;
this.config = config;
}
@Override
public final void init() {
doInit();
}
protected abstract void doInit();
}
```
#### Step 4: 创建具体实现
```java
// 阿里云短信客户端
public class AliyunSmsClient extends AbstractSmsClient {
private IAcsClient client;
@Override
protected void doInit() {
AliyunSmsClientConfig config = (AliyunSmsClientConfig) this.config;
// 初始化阿里云SDK
}
@Override
public SmsSendResultDTO sendSms(SmsSendMessageDTO message) {
// 调用阿里云API
}
}
// 腾讯云短信客户端
public class TencentSmsClient extends AbstractSmsClient {
// 实现类似...
}
```
#### Step 5: 创建工厂类
```java
@Component
public class SmsClientFactoryImpl implements SmsClientFactory {
// 缓存已创建的客户端
private final ConcurrentMap<Long, AbstractSmsClient> channelIdClients = new ConcurrentHashMap<>();
// 类型与客户端类映射
private static final Map<Integer, Class<? extends AbstractSmsClient>> CLIENT_CLASS_MAP = Map.of(
SmsChannelEnum.ALIYUN.getCode(), AliyunSmsClient.class,
SmsChannelEnum.TENCENT.getCode(), TencentSmsClient.class,
SmsChannelEnum.HUAWEI.getCode(), HuaweiSmsClient.class,
SmsChannelEnum.QINIU.getCode(), QiniuSmsClient.class
);
@Override
public SmsClient createOrUpdateSmsClient(SmsChannelProperties properties) {
AbstractSmsClient client = channelIdClients.get(properties.getId());
if (client == null) {
client = createSmsClient(properties);
client.init();
channelIdClients.put(client.getId(), client);
} else {
client.refresh(properties);
}
return client;
}
private AbstractSmsClient createSmsClient(SmsChannelProperties properties) {
Class<? extends AbstractSmsClient> clientClass = CLIENT_CLASS_MAP.get(properties.getCode());
return ReflectUtil.newInstance(clientClass, properties.getId(), properties.getConfig());
}
@Override
public SmsClient getSmsClient(Long channelId) {
return channelIdClients.get(channelId);
}
}
```
### 预期产出
1. SmsClient 接口定义
2. AbstractSmsClient 抽象类
3. 4个具体实现类Aliyun/Tencent/Huawei/Qiniu
4. SmsClientFactory 工厂类
5. 各渠道配置类
```
### 2.3 扩展指南提示词
```markdown
## 任务:在现有工厂中新增产品类型
### 背景
需要在 [现有系统] 中新增支持 [新类型]。
### 扩展步骤
1. **创建配置类**
- 实现 [Config接口]
- 定义新类型特有的配置字段
2. **创建实现类**
- 继承 [抽象基类]
- 实现所有抽象方法
3. **注册到工厂**
- 在枚举中添加新类型
- 在工厂映射中添加对应关系
4. **添加测试**
- 编写单元测试验证功能
### 遵循原则
- 开闭原则:扩展开放,修改关闭
- 新增类型不应修改已有实现类
- 只需在工厂中添加映射关系
```
---
## 3. 策略模式应用提示词
### 3.1 标准提示词模板
```markdown
## 任务:使用策略模式设计 [功能名称]
### 业务背景
[描述需要支持多种算法/行为的场景]
### 设计要求
1. 定义策略接口
- 命名:[行为名称]Strategy 或直接作为核心接口
- 包含所有策略共有的方法
2. 实现具体策略
- 每种算法/行为一个实现类
- 实现类命名:[类型][行为名称]Strategy
3. 上下文使用
- 通过接口引用调用策略
- 可在运行时切换策略
4. 策略选择
- 结合工厂模式创建策略实例
- 根据配置/参数选择策略
### 参考实现
参考项目中 PayClient 接口的多渠道实现。
```
### 3.2 策略模式提示词示例多AI模型适配
```markdown
## 任务使用策略模式设计AI模型适配层
### 业务背景
系统需要支持多种AI模型OpenAI、Claude、百度文心一言、智谱AI、阿里通义千问等。
不同模型的API调用方式、参数格式不同但对外需要提供统一的聊天、图像生成接口。
### 设计要求
#### Step 1: 定义AI模型策略接口
```java
// Spring AI 已经提供了统一接口,我们基于此进行适配
public interface AiModelFactory {
// 获取聊天模型
ChatModel getOrCreateChatModel(AiModelDO model);
// 获取图像模型
ImageModel getOrCreateImageModel(AiModelDO model);
// 获取向量模型
EmbeddingModel getOrCreateEmbeddingModel(AiModelDO model);
}
```
#### Step 2: 实现具体策略(各平台适配)
```java
@Service
public class AiModelFactoryImpl implements AiModelFactory {
// 使用缓存避免重复创建
private static final SingletonCache<ChatModel> CHAT_MODEL_CACHE = new SingletonCache<>();
@Override
public ChatModel getOrCreateChatModel(AiModelDO model) {
String cacheKey = buildCacheKey(model);
return CHAT_MODEL_CACHE.get(cacheKey, () -> doCreateChatModel(model));
}
private ChatModel doCreateChatModel(AiModelDO model) {
AiPlatformEnum platform = AiPlatformEnum.valueOf(model.getPlatform());
String apiKey = getApiKey(model.getKeyId());
String url = model.getUrl();
// 策略选择:根据平台类型创建不同的模型实例
return switch (platform) {
case OPENAI -> buildOpenAIChatModel(apiKey, url);
case ANTHROPIC -> buildAnthropicChatModel(apiKey, url);
case YI_YAN -> buildYiYanChatModel(apiKey, url);
case ZHI_PU -> buildZhiPuChatModel(apiKey, url);
case TONG_YI -> buildTongYiChatModel(apiKey, url);
case DEEP_SEEK -> buildDeepSeekChatModel(apiKey, url);
case OLLAMA -> buildOllamaChatModel(url);
default -> throw new IllegalArgumentException("Unknown platform: " + platform);
};
}
// 各平台具体创建方法
private ChatModel buildOpenAIChatModel(String apiKey, String url) {
OpenAiApi api = OpenAiApi.builder()
.apiKey(apiKey)
.baseUrl(url)
.build();
return OpenAIChatModel.builder()
.openAiApi(api)
.toolCallingManager(getToolCallingManager())
.build();
}
private ChatModel buildZhiPuChatModel(String apiKey, String url) {
ZhiPuApi api = new ZhiPuApi(apiKey);
return new ZhiPuChatModel(api);
}
// 其他平台实现...
}
```
#### Step 3: 定义平台枚举
```java
@Getter
@AllArgsConstructor
public enum AiPlatformEnum {
// 国际平台
OPENAI("OpenAI", "OpenAI"),
ANTHROPIC("Anthropic", "Anthropic Claude"),
GEMINI("Gemini", "Google Gemini"),
// 国内平台
YI_YAN("YiYan", "百度文心一言"),
ZHI_PU("ZhiPu", "智谱AI"),
TONG_YI("TongYi", "阿里通义千问"),
DEEP_SEEK("DeepSeek", "DeepSeek"),
MINI_MAX("MiniMax", "MiniMax"),
// 本地部署
OLLAMA("Ollama", "Ollama 本地模型");
private final String platform;
private final String name;
}
```
#### Step 4: 服务层使用策略
```java
@Service
public class AiChatMessageServiceImpl implements AiChatMessageService {
@Resource
private AiModelFactory aiModelFactory;
@Resource
private AiModelService modelService;
@Override
public Flux<CommonResult<AiChatMessageSendRespVO>> sendChatMessageStream(
AiChatMessageSendReqVO sendReqVO, Long userId) {
// 1. 获取模型配置
AiModelDO model = modelService.getRequiredAiModel(sendReqVO.getModelId());
// 2. 通过工厂获取对应的策略实例ChatModel
ChatModel chatModel = aiModelFactory.getOrCreateChatModel(model);
// 3. 构建消息上下文
List<Message> messages = buildMessages(sendReqVO);
// 4. 调用策略(统一接口,内部实现不同)
return chatModel.stream(new Prompt(messages))
.map(response -> buildResponse(response));
}
}
```
### 设计优势
1. 统一接口所有AI平台通过ChatModel统一调用
2. 易于扩展:新增平台只需添加枚举和创建方法
3. 缓存优化使用Singleton缓存避免重复创建连接
4. 配置驱动:通过数据库配置切换模型
### 预期产出
1. AiPlatformEnum 枚举定义
2. AiModelFactory 接口
3. AiModelFactoryImpl 实现类
4. 各平台ChatModel构建方法
```
### 3.3 策略模式扩展提示词
```markdown
## 任务:在策略模式中新增策略
### 背景
需要在现有 [策略系统] 中新增 [新策略类型]。
### 扩展步骤
1. **确认策略接口方法**
- 查看现有接口定义
- 确定需要实现的方法列表
2. **创建具体策略类**
- 实现策略接口
- 处理特定于新策略的逻辑
3. **更新工厂/上下文**
- 在枚举中添加新类型
- 在工厂中添加创建分支
4. **测试验证**
- 编写单元测试
- 验证与现有策略的兼容性
### 注意事项
- 保持接口一致性
- 处理策略特有的异常
- 考虑配置参数的差异
```
---
## 4. 模板方法模式应用提示词
### 4.1 标准提示词模板
```markdown
## 任务:使用模板方法模式设计 [流程名称]
### 业务背景
[描述需要统一流程但实现细节不同的场景]
### 设计要求
1. 创建抽象类
- 定义模板方法final修饰
- 定义抽象方法(由子类实现)
- 可定义钩子方法(可选实现)
2. 模板方法流程
- 步骤1参数校验
- 步骤2调用子类实现
- 步骤3结果处理
- 步骤4异常处理
3. 具体实现类
- 继承抽象类
- 实现所有抽象方法
### 参考实现
参考项目中 AbstractPayClient 的实现模式。
```
### 4.2 模板方法模式提示词示例:支付客户端抽象
```markdown
## 任务:使用模板方法模式设计支付客户端基类
### 业务背景
系统支持多种支付渠道(微信、支付宝、钱包、模拟支付),每种渠道的下单流程相似:
参数校验 -> 调用第三方API -> 解析响应 -> 处理异常
但具体实现细节不同。
### 设计要求
#### Step 1: 创建抽象基类
```java
@Slf4j
public abstract class AbstractPayClient<Config extends PayClientConfig> implements PayClient<Config> {
protected Long channelId;
protected String channelCode;
protected Config config;
public AbstractPayClient(Long channelId, String channelCode, Config config) {
this.channelId = channelId;
this.channelCode = channelCode;
this.config = config;
}
// ==================== 模板方法 ====================
/**
* 统一下单 - 模板方法
* 定义固定的执行流程,子类不能修改
*/
@Override
public final PayOrderRespDTO unifiedOrder(PayOrderUnifiedReqDTO reqDTO) {
// 1. 参数校验
ValidationUtils.validate(reqDTO);
// 2. 执行下单
try {
return doUnifiedOrder(reqDTO);
} catch (Throwable ex) {
// 3. 统一异常处理
log.error("[unifiedOrder] 渠道[{}]下单异常", channelCode, ex);
throw buildPayException(ex);
}
}
/**
* 统一退款 - 模板方法
*/
@Override
public final PayRefundRespDTO unifiedRefund(PayRefundUnifiedReqDTO reqDTO) {
ValidationUtils.validate(reqDTO);
try {
return doUnifiedRefund(reqDTO);
} catch (Throwable ex) {
log.error("[unifiedRefund] 渠道[{}]退款异常", channelCode, ex);
throw buildPayException(ex);
}
}
// ==================== 抽象方法(子类必须实现) ====================
/**
* 执行下单 - 由子类实现具体调用第三方API的逻辑
*/
protected abstract PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws Throwable;
/**
* 执行退款 - 由子类实现具体调用第三方API的逻辑
*/
protected abstract PayRefundRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) throws Throwable;
/**
* 初始化客户端 - 由子类实现SDK初始化
*/
protected abstract void doInit();
/**
* 解析支付回调
*/
protected abstract PayOrderRespDTO doParseOrderNotify(PayNotifyDataDTO notifyData) throws Throwable;
// ==================== 钩子方法(子类可选实现) ====================
/**
* 刷新配置 - 默认实现,子类可覆盖
*/
public void refresh(Config config) {
this.config = config;
doInit();
}
// ==================== 工具方法 ====================
protected PayException buildPayException(Throwable ex) {
if (ex instanceof PayException) {
return (PayException) ex;
}
return new PayException(ex.getMessage(), ex);
}
}
```
#### Step 2: 创建具体实现
```java
// 支付宝支付客户端
public class AlipayQrPayClient extends AbstractPayClient<AlipayPayClientConfig> {
private AlipayClient client;
public AlipayQrPayClient(Long channelId, AlipayPayClientConfig config) {
super(channelId, PayChannelEnum.ALIPAY_QR.getCode(), config);
}
@Override
protected void doInit() {
AlipayPayClientConfig config = this.config;
// 初始化支付宝SDK
this.client = new DefaultAlipayClient(
config.getServerUrl(),
config.getAppId(),
config.getPrivateKey(),
config.getFormat(),
config.getCharset(),
config.getAlipayPublicKey(),
config.getSignType()
);
}
@Override
protected PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws Throwable {
// 1. 构建支付宝请求
AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
request.setBizContent(buildBizContent(reqDTO));
request.setNotifyUrl(reqDTO.getNotifyUrl());
// 2. 调用支付宝API
AlipayTradePrecreateResponse response = client.execute(request);
// 3. 解析响应
if (response.isSuccess()) {
return PayOrderRespDTO.builder()
.channelOrderNo(response.getOutTradeNo())
.qrCode(response.getQrCode())
.build();
} else {
throw new PayException(response.getSubMsg());
}
}
@Override
protected PayRefundRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) throws Throwable {
// 实现退款逻辑...
}
@Override
protected PayOrderRespDTO doParseOrderNotify(PayNotifyDataDTO notifyData) throws Throwable {
// 解析回调...
}
}
// 微信支付客户端
public class WxNativePayClient extends AbstractPayClient<WxPayClientConfig> {
private WxPayService wxPayService;
public WxNativePayClient(Long channelId, WxPayClientConfig config) {
super(channelId, PayChannelEnum.WX_NATIVE.getCode(), config);
}
@Override
protected void doInit() {
WxPayClientConfig config = this.config;
// 初始化微信支付SDK
WxPayConfig wxConfig = new WxPayConfig();
wxConfig.setAppId(config.getAppId());
wxConfig.setMchId(config.getMchId());
wxConfig.setPrivateKeyPath(config.getPrivateKeyPath());
// ...
this.wxPayService = new WxPayService();
this.wxPayService.setConfig(wxConfig);
}
@Override
protected PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws Throwable {
// 使用WxJava SDK调用微信支付
WxPayNativeOrderResult result = wxPayService.createOrder(
buildWxOrderRequest(reqDTO)
);
return PayOrderRespDTO.builder()
.qrCode(result.getCodeUrl())
.build();
}
// 其他方法实现...
}
```
### 模板方法优势
1. **流程标准化**:所有渠道遵循统一的处理流程
2. **代码复用**:参数校验、异常处理等公共逻辑在基类实现
3. **易于维护**:修改公共逻辑只需修改基类
4. **扩展性强**:新增渠道只需继承基类实现抽象方法
### 预期产出
1. AbstractPayClient 抽象基类
2. 各渠道具体实现类
3. 统一的异常处理机制
```
### 4.3 模板方法扩展提示词
```markdown
## 任务:在模板方法模式中新增实现
### 背景
需要在现有 [模板类] 的基础上新增 [新实现类型]。
### 扩展步骤
1. **创建具体实现类**
- 继承抽象基类
- 实现所有抽象方法
2. **初始化处理**
- 在 doInit() 中初始化第三方SDK
- 配置必要的认证信息
3. **实现核心方法**
- doUnifiedXxx()调用第三方API
- doParseXxxNotify():解析回调数据
4. **注册到工厂**
- 在工厂中添加创建逻辑
- 在枚举中添加类型定义
### 代码模板
```java
public class XxxPayClient extends AbstractPayClient<XxxPayClientConfig> {
private XxxSdkClient client; // 第三方SDK客户端
public XxxPayClient(Long channelId, XxxPayClientConfig config) {
super(channelId, PayChannelEnum.XXX.getCode(), config);
}
@Override
protected void doInit() {
// 初始化SDK客户端
this.client = new XxxSdkClient.Builder()
.appId(config.getAppId())
.apiKey(config.getApiKey())
.build();
}
@Override
protected PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws Throwable {
// 调用第三方API
XxxOrderRequest request = buildRequest(reqDTO);
XxxOrderResponse response = client.createOrder(request);
// 转换响应
return PayOrderRespDTO.builder()
.channelOrderNo(response.getOrderId())
.build();
}
// 实现其他抽象方法...
}
```
```
---
## 5. 实际案例分析
### 5.1 案例一:多渠道支付系统
#### 业务场景
系统需要支持微信支付、支付宝、钱包支付、模拟支付等多种支付渠道,每种渠道有不同的:
- SDK接入方式
- 配置参数
- API调用方式
- 响应解析方式
#### 设计方案
**模式组合**:工厂模式 + 策略模式 + 模板方法模式
```
┌─────────────────────────────────────────────────────────────┐
│ PayClientFactory │
│ (工厂模式 - 创建客户端) │
│ │
│ getPayClient(channelId) ──> 缓存中获取或创建客户端实例 │
└──────────────────────┬──────────────────────────────────────┘
│ 创建
┌─────────────────────────────────────────────────────────────┐
│ AbstractPayClient │
│ (模板方法模式 - 统一流程骨架) │
│ │
│ unifiedOrder() { │
│ validate(); // 参数校验 │
│ doUnifiedOrder(); // 调用子类实现 │
│ handleException(); // 异常处理 │
│ } │
└──────────────────────┬──────────────────────────────────────┘
│ 继承
┌────────────┼────────────┬────────────┐
▼ ▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ AlipayClient │ │ WxPayClient │ │WalletClient │ │ MockClient │
│ (支付宝) │ │ (微信) │ │ (钱包) │ │ (模拟) │
│ │ │ │ │ │ │ │
│ 策略模式实现 │ │ 策略模式实现 │ │ 策略模式实现 │ │ 策略模式实现 │
└──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘
```
#### 关键代码
```java
// 策略接口PayClient- 定义统一行为
public interface PayClient<Config extends PayClientConfig> {
Long getId();
PayOrderRespDTO unifiedOrder(PayOrderUnifiedReqDTO reqDTO);
PayRefundRespDTO unifiedRefund(PayRefundUnifiedReqDTO reqDTO);
PayTransferRespDTO unifiedTransfer(PayTransferUnifiedReqDTO reqDTO);
}
// 模板方法AbstractPayClient- 定义流程骨架
public abstract class AbstractPayClient<Config extends PayClientConfig> implements PayClient<Config> {
@Override
public final PayOrderRespDTO unifiedOrder(PayOrderUnifiedReqDTO reqDTO) {
ValidationUtils.validate(reqDTO);
try {
return doUnifiedOrder(reqDTO); // 子类实现
} catch (Throwable ex) {
throw buildPayException(ex);
}
}
protected abstract PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws Throwable;
}
// 工厂PayClientFactory- 创建和管理客户端
@Component
public class PayClientFactoryImpl implements PayClientFactory {
private final ConcurrentMap<Long, PayClient<?>> clients = new ConcurrentHashMap<>();
private static final Map<String, Class<? extends PayClient>> CLIENT_CLASS_MAP = Map.of(
"wx_pub", WxPubPayClient.class,
"wx_native", WxNativePayClient.class,
"alipay_wap", AlipayWapPayClient.class,
"alipay_qr", AlipayQrPayClient.class,
"wallet", WalletPayClient.class,
"mock", MockPayClient.class
);
@Override
public PayClient getPayClient(Long channelId) {
return clients.computeIfAbsent(channelId, this::createPayClient);
}
}
```
#### 扩展指南:新增银联支付
```markdown
## 任务:新增银联支付渠道
### 步骤
1. **创建配置类**
```java
@Data
public class UnionPayClientConfig implements PayClientConfig {
private String merchantId; // 商户号
private String apiKey; // API密钥
private String certPath; // 证书路径
private String certPassword; // 证书密码
}
```
2. **创建客户端类**
```java
public class UnionPayQrPayClient extends AbstractPayClient<UnionPayClientConfig> {
@Override
protected void doInit() {
// 初始化银联SDK
}
@Override
protected PayOrderRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws Throwable {
// 调用银联下单API
}
// 实现其他方法...
}
```
3. **注册到工厂**
```java
CLIENT_CLASS_MAP.put("union_pay_qr", UnionPayQrPayClient.class);
```
4. **添加枚举**
```java
UNION_PAY_QR("union_pay_qr", "银联扫码支付");
```
```
---
### 5.2 案例二:多存储类型文件系统
#### 业务场景
系统需要支持多种文件存储方式本地存储、S3MinIO/OSS/COS、FTP、SFTP、数据库存储。不同存储方式的
- 配置参数不同
- 上传/下载/删除实现不同
- 访问URL生成方式不同
#### 设计方案
**模式组合**:策略模式 + 工厂模式 + 模板方法模式
```
┌─────────────────────────────────────────────────────────────┐
│ FileClientFactory │
│ (工厂模式 - 创建客户端) │
└──────────────────────┬──────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ AbstractFileClient │
│ (模板方法模式 - 统一流程) │
└──────────────────────┬──────────────────────────────────────┘
┌────────────┼────────────┬────────────┬───────────┐
▼ ▼ ▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌─────────────┐ ┌─────────────┐
│LocalFileClient│ │ S3FileClient │ │FtpFileClient│ │SftpFileClient│ │DBFileClient │
│ (本地) │ │ (S3/OSS) │ │ (FTP) │ │ (SFTP) │ │ (数据库) │
└──────────────┘ └──────────────┘ └──────────────┘ └─────────────┘ └─────────────┘
```
#### 关键代码
```java
// 策略接口
public interface FileClient {
Long getId();
void upload(byte[] content, String path, String type);
byte[] getContent(String path);
void delete(String path);
String getPresignedUrl(String path, int timeout);
}
// 模板方法
public abstract class AbstractFileClient<Config extends FileClientConfig> implements FileClient {
protected Long id;
protected Config config;
public AbstractFileClient(Long id, Config config) {
this.id = id;
this.config = config;
}
public final void init() {
doInit();
}
protected abstract void doInit();
}
// 枚举定义类型与类映射
@Getter
@AllArgsConstructor
public enum FileStorageEnum {
LOCAL(10, LocalFileClientConfig.class, LocalFileClient.class),
S3(20, S3FileClientConfig.class, S3FileClient.class),
FTP(30, FtpFileClientConfig.class, FtpFileClient.class),
SFTP(40, SftpFileClientConfig.class, SftpFileClient.class),
DATABASE(50, NoneFileClientConfig.class, DBFileClient.class);
private final Integer storage;
private final Class<? extends FileClientConfig> configClass;
private final Class<? extends FileClient> clientClass;
}
```
---
### 5.3 案例三多AI模型适配
#### 业务场景
系统需要支持多种AI平台OpenAI、Claude、文心一言、智谱AI、通义千问、DeepSeek、Ollama本地部署等。不同平台
- API格式不同
- 认证方式不同
- 响应结构不同
#### 设计方案
**模式组合**:工厂模式 + 策略模式
```
┌─────────────────────────────────────────────────────────────┐
│ AiModelFactory │
│ (工厂模式 - 创建模型实例) │
│ │
│ getOrCreateChatModel(model) -> 缓存获取或创建 │
└──────────────────────┬──────────────────────────────────────┘
│ switch by platform
┌─────────────────────────────────────────────────────────────┐
│ ChatModel │
│ (Spring AI 统一接口 - 策略模式) │
│ │
│ call(Prompt) -> ChatResponse │
│ stream(Prompt) -> Flux<ChatResponse> │
└──────────────────────┬──────────────────────────────────────┘
│ 实现
┌─────────────────┼─────────────────┬─────────────────┐
▼ ▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│OpenAIChat │ │ZhiPuChat │ │DeepSeekChat │ │OllamaChat │
│ Model │ │ Model │ │ Model │ │ Model │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
```
#### 关键代码
```java
// 工厂实现
@Service
public class AiModelFactoryImpl implements AiModelFactory {
@Override
public ChatModel getOrCreateChatModel(AiModelDO model) {
String cacheKey = buildCacheKey(model);
return Singleton.get(cacheKey, () -> doCreateChatModel(model));
}
private ChatModel doCreateChatModel(AiModelDO model) {
AiPlatformEnum platform = AiPlatformEnum.valueOf(model.getPlatform());
return switch (platform) {
case OPENAI -> buildOpenAIChatModel(model);
case ANTHROPIC -> buildAnthropicChatModel(model);
case ZHI_PU -> buildZhiPuChatModel(model);
case DEEP_SEEK -> buildDeepSeekChatModel(model);
case OLLAMA -> buildOllamaChatModel(model);
// ... 其他平台
};
}
}
```
---
## 6. 模式组合使用
### 6.1 三种模式的协作关系
```
┌────────────────────────────────────────────────────────────────┐
│ 业务场景 │
│ "需要支持多种XXX统一调用方式" │
└────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────┐
│ 工厂模式 │
│ │
│ 职责:创建具体实例 │
│ - 根据类型/配置创建对应的实现类实例 │
│ - 缓存已创建的实例 │
│ - 支持配置热刷新 │
│ │
│ 产出Product 接口的实现类实例 │
└────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────┐
│ 策略模式 │
│ │
│ 职责:定义统一行为接口 │
│ - 定义所有实现类共有的方法 │
│ - 不同实现类提供不同的算法/行为 │
│ - 运行时可切换 │
│ │
│ 产出Product 接口定义 │
└────────────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────────────┐
│ 模板方法模式 │
│ │
│ 职责:定义统一流程骨架 │
│ - 定义模板方法final控制执行流程 │
│ - 定义抽象方法由子类实现 │
│ - 复用公共逻辑(校验、异常处理、日志) │
│ │
│ 产出AbstractProduct 抽象类 │
└────────────────────────────────────────────────────────────────┘
```
### 6.2 组合使用提示词模板
```markdown
## 任务:使用设计模式组合设计 [系统名称]
### 业务场景
[描述业务需求,强调多类型支持、统一调用、流程标准化]
### 设计要求
#### 1. 策略层设计(定义行为)
**创建策略接口**
```java
public interface [Product] {
// 核心业务方法
Result doSomething(Request request);
}
```
#### 2. 模板层设计(定义流程)
**创建抽象基类**
```java
public abstract class Abstract[Product] implements [Product] {
// 模板方法
@Override
public final Result doSomething(Request request) {
// 1. 参数校验
validate(request);
// 2. 执行业务
try {
return doDoSomething(request);
} catch (Exception e) {
// 3. 异常处理
return handleException(e);
}
}
// 抽象方法
protected abstract Result doDoSomething(Request request);
protected abstract void doInit();
}
```
#### 3. 工厂层设计(创建实例)
**创建工厂接口和实现**
```java
public interface [Product]Factory {
[Product] get[Product](Long id);
[Product] create[Product](Config config);
}
@Component
public class [Product]FactoryImpl implements [Product]Factory {
private final ConcurrentMap<Long, [Product]> cache = new ConcurrentHashMap<>();
@Override
public [Product] get[Product](Long id) {
return cache.computeIfAbsent(id, this::create[Product]);
}
}
```
#### 4. 具体实现
**为每种类型创建实现类**
```java
public class [Type][Product] extends Abstract[Product] {
@Override
protected void doInit() {
// 初始化特定类型
}
@Override
protected Result doDoSomething(Request request) {
// 实现特定逻辑
}
}
```
### 预期产出
1. [Product] 接口定义
2. Abstract[Product] 抽象类
3. [Product]Factory 工厂类
4. 多个具体实现类
5. 类型枚举定义
```
### 6.3 扩展新类型的标准流程
```markdown
## 任务:在组合模式系统中扩展新类型
### 扩展流程图
```
┌─────────────────┐
│ 1. 创建配置类 │ 实现 Config 接口,定义新类型配置字段
└────────┬────────┘
┌─────────────────┐
│ 2. 创建实现类 │ 继承抽象基类,实现所有抽象方法
└────────┬────────┘
┌─────────────────┐
│ 3. 添加枚举值 │ 在类型枚举中添加新类型定义
└────────┬────────┘
┌─────────────────┐
│ 4. 注册到工厂 │ 在工厂的映射Map中添加类型-类关系
└────────┬────────┘
┌─────────────────┐
│ 5. 编写测试 │ 验证新类型功能正确性
└─────────────────┘
```
### 扩展代码模板
```java
// Step 1: 配置类
@Data
public class [NewType]Config implements Config {
private String field1;
private String field2;
// ...
}
// Step 2: 实现类
public class [NewType][Product] extends Abstract[Product]<[NewType]Config> {
public [NewType][Product](Long id, [NewType]Config config) {
super(id, config);
}
@Override
protected void doInit() {
// 初始化逻辑
}
@Override
protected Result doDoSomething(Request request) {
// 业务逻辑
}
}
// Step 3: 枚举
[NEW_TYPE](100, "[NewType]", "新类型描述");
// Step 4: 工厂注册
CLIENT_MAP.put(TypeEnum.NEW_TYPE, [NewType][Product].class);
// Step 5: 测试
@Test
void test[NewType]() {
// ...
}
```
```
---
## 附录:项目中的设计模式文件索引
### 工厂模式实现位置
| 模块 | 工厂类 | 路径 |
|-----|-------|------|
| pay | PayClientFactoryImpl | yudao-module-pay/.../pay/core/client/impl/PayClientFactoryImpl.java |
| infra | FileClientFactory | yudao-module-infra/.../file/core/client/FileClientFactory.java |
| ai | AiModelFactoryImpl | yudao-module-ai/.../framework/ai/core/model/AiModelFactoryImpl.java |
### 策略模式实现位置
| 模块 | 策略接口 | 实现类 |
|-----|---------|--------|
| pay | PayClient | AlipayPayClient, WxPayClient, WalletPayClient, MockPayClient |
| infra | FileClient | LocalFileClient, S3FileClient, FtpFileClient, DBFileClient |
| ai | ChatModel (Spring AI) | OpenAIChatModel, ZhiPuChatModel, DeepSeekChatModel |
### 模板方法模式实现位置
| 模块 | 抽象类 | 路径 |
|-----|-------|------|
| pay | AbstractPayClient | yudao-module-pay/.../pay/core/client/impl/AbstractPayClient.java |
| infra | AbstractFileClient | yudao-module-infra/.../file/core/client/AbstractFileClient.java |
---
> 文档版本1.0.0
> 更新日期2026-03-18
> 维护者Technical Writer Agent