196 lines
6.1 KiB
Markdown
196 lines
6.1 KiB
Markdown
# Tool V2 - 可拼接式设计
|
||
|
||
## 🎯 设计理念
|
||
|
||
### 核心原则
|
||
1. **松耦合** - 工具之间通过接口通信,不直接依赖
|
||
2. **可替换** - 任何工具都可以被同类工具替换
|
||
3. **可组合** - 像乐高一样自由组合
|
||
4. **依赖注入** - 通过服务名获取依赖,而非硬编码
|
||
|
||
---
|
||
|
||
## 📦 架构示意图
|
||
|
||
```
|
||
┌─────────────────────────────────────────┐
|
||
│ IToolContext (上下文) │
|
||
│ ┌─────────────┐ ┌───────────────┐ │
|
||
│ │ Data Store │ │ Service Bus │ │
|
||
│ └─────────────┘ └───────────────┘ │
|
||
└─────────────────────────────────────────┘
|
||
↑ ↑
|
||
│ │
|
||
┌────────┴────────┬───────┴────────┐
|
||
│ │ │
|
||
┌─────────┐ ┌──────────┐ ┌──────────┐
|
||
│ Tool A │ │ Tool B │ │ Tool C │
|
||
│provides │ │requires │ │provides │
|
||
│storage │ │storage │ │generator │
|
||
└─────────┘ └──────────┘ └──────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## 💡 使用示例
|
||
|
||
### 场景1:使用MySQL存储
|
||
|
||
```typescript
|
||
const toolManager = new ToolManager();
|
||
|
||
// 注册工具(顺序无关!)
|
||
toolManager.register(new CardGeneratorTool());
|
||
toolManager.register(new MySQLStorageTool()); // 提供storage
|
||
toolManager.register(new AccountGeneratorTool());
|
||
|
||
// 自动解决依赖并初始化
|
||
await toolManager.initializeAll();
|
||
|
||
// 使用
|
||
const context = toolManager.getContext();
|
||
const cardGen = context.getService<IGeneratorService>('card-generator');
|
||
const card = await cardGen.generate();
|
||
```
|
||
|
||
### 场景2:切换到Redis存储(只需改一行!)
|
||
|
||
```typescript
|
||
const toolManager = new ToolManager();
|
||
|
||
toolManager.register(new CardGeneratorTool());
|
||
toolManager.register(new RedisStorageTool()); // 替换成Redis!
|
||
toolManager.register(new AccountGeneratorTool());
|
||
|
||
await toolManager.initializeAll(); // 其他代码完全不用改
|
||
```
|
||
|
||
---
|
||
|
||
## 🔌 可拼接的优势
|
||
|
||
### 1. 完全解耦
|
||
|
||
```typescript
|
||
// ❌ 旧设计 - 耦合
|
||
class CardGenerator {
|
||
constructor(private db: MySQLDatabase) {} // 硬编码依赖MySQL
|
||
}
|
||
|
||
// ✅ 新设计 - 解耦
|
||
class CardGeneratorTool {
|
||
readonly requires = ['storage']; // 只声明需要storage接口
|
||
|
||
async initialize(context: IToolContext) {
|
||
// 不关心谁提供storage,只要符合IStorageService接口即可
|
||
const storage = context.getService<IStorageService>('storage');
|
||
}
|
||
}
|
||
```
|
||
|
||
### 2. 任意组合
|
||
|
||
```typescript
|
||
// 组合1:MySQL + 本地卡生成器
|
||
toolManager.register(new MySQLStorageTool());
|
||
toolManager.register(new LocalCardGenerator());
|
||
|
||
// 组合2:Redis + API卡生成器
|
||
toolManager.register(new RedisStorageTool());
|
||
toolManager.register(new APICardGenerator());
|
||
|
||
// 组合3:内存存储 + 测试卡生成器(用于测试)
|
||
toolManager.register(new MemoryStorageTool());
|
||
toolManager.register(new MockCardGenerator());
|
||
```
|
||
|
||
### 3. 插件化
|
||
|
||
```typescript
|
||
// 添加新功能,完全不影响现有工具
|
||
toolManager.register(new LoggerTool()); // 日志工具
|
||
toolManager.register(new MetricsTool()); // 监控工具
|
||
toolManager.register(new CacheTool()); // 缓存工具
|
||
```
|
||
|
||
---
|
||
|
||
## 🏗️ 在Adapter中使用
|
||
|
||
### windsurf-adapter.ts
|
||
|
||
```typescript
|
||
import { ToolManager } from '../../src/tools/ToolManager';
|
||
import { AccountGeneratorTool } from '../../src/tools/AccountGeneratorTool';
|
||
import { CardGeneratorTool } from '../../src/tools/CardGeneratorTool';
|
||
import { MySQLStorageTool } from '../../src/tools/MySQLStorageTool';
|
||
|
||
class WindsurfAdapter implements ISiteAdapter {
|
||
private toolManager: ToolManager;
|
||
|
||
constructor() {
|
||
this.toolManager = new ToolManager();
|
||
|
||
// 拼接需要的工具(像搭积木)
|
||
this.toolManager.register(new MySQLStorageTool());
|
||
this.toolManager.register(new AccountGeneratorTool());
|
||
this.toolManager.register(new CardGeneratorTool());
|
||
// 想要更多功能?继续注册!
|
||
// this.toolManager.register(new EmailHandlerTool());
|
||
// this.toolManager.register(new CaptchaSolverTool());
|
||
}
|
||
|
||
async initialize(context: any): Promise<void> {
|
||
// 一键初始化所有工具
|
||
await this.toolManager.initializeAll();
|
||
|
||
const toolContext = this.toolManager.getContext();
|
||
|
||
// 生成账号
|
||
if (!context.data.account?.email) {
|
||
const accountGen = toolContext.getService('account-generator');
|
||
context.data.account = await accountGen.generate();
|
||
}
|
||
}
|
||
|
||
getHandlers() {
|
||
const toolContext = this.toolManager.getContext();
|
||
|
||
return {
|
||
generateCard: async () => {
|
||
const cardGen = toolContext.getService('card-generator');
|
||
return await cardGen.generate();
|
||
},
|
||
|
||
saveToDatabase: async () => {
|
||
const storage = toolContext.getService('storage');
|
||
await storage.save('account:xxx', this.context.data.account);
|
||
}
|
||
};
|
||
}
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## ✅ 对比总结
|
||
|
||
| 特性 | V1设计 | V2设计 |
|
||
|------|--------|--------|
|
||
| **耦合度** | 高(直接依赖) | 低(接口依赖) |
|
||
| **可替换** | 难(需改代码) | 易(改配置) |
|
||
| **测试** | 难(需mock具体类) | 易(mock接口) |
|
||
| **扩展** | 难(需修改现有代码) | 易(只需添加工具) |
|
||
| **维护** | 难(改一处影响多处) | 易(工具独立) |
|
||
|
||
---
|
||
|
||
## 🎉 这才是真正的"可拼接"!
|
||
|
||
就像:
|
||
- **USB接口** - 不管是键盘、鼠标、U盘,只要符合USB规范就能插上
|
||
- **乐高积木** - 不同的积木可以自由组合
|
||
- **插座** - 不管什么电器,只要符合电压规范就能用
|
||
|
||
**工具之间通过标准接口(storage、generator、validator等)通信,而不是硬编码依赖关系!**
|