Java 工厂模式 + 策略模式实战:工具管理器的设计与实现

在日常开发中,我们经常会遇到「需要根据不同的业务逻辑选择不同实现类」的场景。比如:文件操作可能有读取、写入、修改、删除 等多种方式,如果我们在业务代码中使用大量的 if-else 来区分,会导致代码臃肿且难以维护。

本文将结合 工厂模式(Factory Pattern)策略模式(Strategy Pattern) ,通过一个 工具管理器(ToolManager) 的案例,来展示如何优雅地管理和调用不同的工具。


一、模式介绍

1. 工厂模式

工厂模式的核心思想是:将对象的创建与使用解耦

调用方不需要关心对象的具体实现,而只需要通过工厂方法获取对象即可。

在本文中,ToolManager 就是一个工厂,负责 统一注册和管理所有工具实例

2. 策略模式

策略模式强调:定义一系列算法(策略),并且可以在运行时自由切换

调用方只需要依赖抽象接口,而不需要知道具体的实现细节。

在本文中,每个工具(如 FileReadToolFileWriteTool)就是一个具体策略,统一实现了 BaseTool 抽象类。


二、使用场景

这种「工厂模式 + 策略模式」的组合,非常适合以下场景:

  1. 多实现类管理

    比如支付系统中的 微信支付 / 支付宝支付 / 银行卡支付,都可以作为不同的策略,由工厂统一管理。

  2. 动态扩展

    新增一种工具(比如 FileUploadTool),只需要实现 BaseTool 并交给工厂管理,而不需要改动原有逻辑,符合 开闭原则

  3. 业务逻辑解耦

    调用方只依赖抽象接口(BaseTool),而不依赖具体实现,业务逻辑更加清晰。


三、代码示例

下面给出完整的示例代码,使用 Spring + Hutool 结合实现。

1. 定义工具基类(抽象类)

java 复制代码
package com.ming.mingaicode.ai.tools;

import cn.hutool.json.JSONObject;

/**
 * 工具基类,定义所有工具的通用接口
 */
public abstract class BaseTool {
    public abstract String getToolName();
    public abstract String getDisplayName();

    public String generateToolRequestResponse() {
        return String.format("\n\n[选择工具🔧] %s\n\n", getDisplayName());
    }

    public abstract String generateToolExecutedResult(JSONObject arguments);
}

2. 定义多个工具实现类(具体策略)

文件目录读取工具
java 复制代码
@Slf4j
@Component
public class FileDirReadTool extends BaseTool{
    @Override
    public String getToolName() { return "readDir"; }

    @Override
    public String getDisplayName() { return "读取目录"; }

    @Override
    public String generateToolExecutedResult(JSONObject arguments) {
        String relativeDirPath = arguments.getStr("relativeDirPath");
        if (StrUtil.isEmpty(relativeDirPath)) {
            relativeDirPath = "根目录";
        }
        return String.format("[工具调用] %s %s", getDisplayName(), relativeDirPath);
    }
}
文件修改工具
java 复制代码
@Slf4j
@Component
public class FileModifyTool extends BaseTool{
    @Override
    public String getToolName() { return "modifyFile"; }

    @Override
    public String getDisplayName() { return "修改文件"; }

    @Override
    public String generateToolExecutedResult(JSONObject arguments) {
        String relativeFilePath = arguments.getStr("relativeFilePath");
        String oldContent = arguments.getStr("oldContent");
        String newContent = arguments.getStr("newContent");
        return String.format("""
                [工具调用] %s %s
                
                替换前:
                ```
                %s
                ```
                
                替换后:
                ```
                %s
                ```
                """, getDisplayName(), relativeFilePath, oldContent, newContent);
    }
}
文件写入工具
java 复制代码
@Slf4j
@Component
public class FileWriteTool extends BaseTool{
    @Override
    public String getToolName() { return "writeFile"; }

    @Override
    public String getDisplayName() { return "写入文件"; }

    @Override
    public String generateToolExecutedResult(JSONObject arguments) {
        String relativeFilePath = arguments.getStr("relativeFilePath");
        String suffix = FileUtil.getSuffix(relativeFilePath);
        String content = arguments.getStr("content");
        return String.format("""
                        [工具调用] %s %s
                        ```%s
                        %s
                        ```
                        """, getDisplayName(), relativeFilePath, suffix, content);
    }
}

(其他工具如 FileReadToolFileDeleteTool 也类似,不再赘述)


3. 工厂管理器(ToolManager)

java 复制代码
@Slf4j
@Component
public class ToolManager {
    @Resource
    private BaseTool[] tools;

    private final Map<String, BaseTool> toolMap = new HashMap<>();

    @PostConstruct
    public void initTools() {
        for (BaseTool tool : tools) {
            toolMap.put(tool.getToolName(), tool);
            log.info("注册工具: {} -> {}", tool.getToolName(), tool.getDisplayName());
        }
        log.info("工具管理器初始化完成,共注册 {} 个工具", toolMap.size());
    }

    public BaseTool getTool(String toolName) {
        return toolMap.get(toolName);
    }

    public BaseTool[] getAllTools() {
        return tools;
    }
}

4. 使用方式

java 复制代码
// 处理工具请求
case TOOL_REQUEST -> {
    BaseTool tool = toolManager.getTool(toolRequestMessage.getName());
    return tool.generateToolRequestResponse();
}

// 处理工具执行结果
case TOOL_EXECUTED -> {
    BaseTool tool = toolManager.getTool(toolExecutedMessage.getName());
    String result = tool.generateToolExecutedResult(jsonObject);
    return String.format("\n\n%s\n\n", result);
}

四、方法解析

  1. 抽象基类 BaseTool

    • 统一了所有工具的接口(名字、展示名、执行结果格式化)。

    • 保证扩展新工具时,调用方无需修改原有逻辑。

  2. 具体工具类(策略)

    • 每个工具都实现了自己的 generateToolExecutedResult 方法,遵循 策略模式
  3. ToolManager 工厂

    • 自动扫描所有 BaseTool 的子类(Spring 注入)。

    • 通过 Map 保存工具名称和实例的映射,支持快速查找和调用。


五、总结

本文通过 工厂模式 + 策略模式 结合的方式,构建了一个可扩展、可维护的 工具管理器

  • 工厂模式负责统一管理实例

  • 策略模式负责封装不同的业务逻辑

  • 新增功能时,只需要 新增一个实现类 ,无需修改现有代码,真正做到 开闭原则

这种设计思想在 支付系统、权限系统、AI 工具调用 等场景下都有广泛应用,能够显著提升代码的可维护性和扩展性。

相关推荐
小信丶2 小时前
Spring Boot请求体缺失异常分析与解决方案
java·spring boot·后端
DokiDoki之父2 小时前
JDBC入门
java·sql·mysql
零千叶3 小时前
Spring / Spring Boot 常用注解
java·spring boot·后端
途经六月的绽放3 小时前
Docker Compose 从入门到实践
java·docker
用户6120414922133 小时前
支持eclipse+idea+mysql5和8的javaweb学生信息管理系统
java·javascript·后端
城管不管3 小时前
SpringBoot与反射
java·开发语言·前端
我不是混子3 小时前
说说建造者模式
java·后端
一 乐3 小时前
智慧外贸平台|基于Java+vue的智慧外贸平台系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·外贸服务系统