对应源码: conversation.rs:429-456 → StaticToolExecutor handlers: BTreeMap ← "名字 → 函数" 的映射 fn execute(&mut self, tool_name: &str, input: &str) → 按名字查找并调用 Agent 系统有很多工具 (bash, read, write, grep, glob, ...), 每个工具的执行逻辑不同。怎么组织? 方案 A (if/elif 地狱)
()
| 578 | # ============================================================ |
| 579 | |
| 580 | def lesson_4_registry_pattern(): |
| 581 | """ |
| 582 | 对应源码: |
| 583 | conversation.rs:429-456 → StaticToolExecutor |
| 584 | handlers: BTreeMap<String, ToolHandler> ← "名字 → 函数" 的映射 |
| 585 | fn execute(&mut self, tool_name: &str, input: &str) → 按名字查找并调用 |
| 586 | |
| 587 | Agent 系统有很多工具 (bash, read, write, grep, glob, ...), |
| 588 | 每个工具的执行逻辑不同。怎么组织? |
| 589 | |
| 590 | 方案 A (if/elif 地狱): |
| 591 | if tool == "bash": do_bash() |
| 592 | elif tool == "read": do_read() |
| 593 | elif tool == "write": do_write() |
| 594 | elif ... (50 个 elif) |
| 595 | → 每加一个工具就要改这个 if 链, 容易出错 |
| 596 | |
| 597 | 方案 B (注册表): |
| 598 | registry["bash"] = do_bash |
| 599 | registry["read"] = do_read |
| 600 | result = registry[tool](input) |
| 601 | → 加工具只需 register(), 查找和执行完全解耦 |
| 602 | |
| 603 | 日常类比: 手机通讯录 |
| 604 | ──────────────────── |
| 605 | 你不会记住所有人的电话号码。 |
| 606 | 你把 "名字 → 号码" 存进通讯录, 需要时按名字搜索。 |
| 607 | 注册表就是 "工具名 → 处理函数" 的通讯录。 |
| 608 | """ |
| 609 | print("=" * 60) |
| 610 | print("第四课: 注册表模式 — 电话簿: 按名字查找处理函数") |
| 611 | print("=" * 60) |
| 612 | |
| 613 | # ---- 反面教材 ---- |
| 614 | print() |
| 615 | print(" 反面教材 (if/elif 地狱):") |
| 616 | print(" ─────────────────────") |
| 617 | print(" def execute(tool, input):") |
| 618 | print(" if tool == 'bash': return run_bash(input)") |
| 619 | print(" elif tool == 'read': return read_file(input)") |
| 620 | print(" elif tool == 'write': return write_file(input)") |
| 621 | print(" elif tool == 'grep': return grep_file(input)") |
| 622 | print(" elif ... # 每加一个工具就改这里!") |
| 623 | print() |
| 624 | |
| 625 | # ---- 正面教材: 注册表 ---- |
| 626 | print(" 正面教材 (注册表):") |
| 627 | print(" ────────────────") |
| 628 | |
| 629 | # 对应 conversation.rs:429-456 |
| 630 | class ToolRegistry: |
| 631 | """ |
| 632 | 工具注册表 |
| 633 | 核心数据结构: dict[str, Callable] |
| 634 | 对应 Rust: BTreeMap<String, Box<dyn FnMut(&str) -> Result<String, ToolError>>> |
| 635 | """ |
| 636 | def __init__(self): |
| 637 | self._handlers: dict[str, Callable[[str], str]] = {} |
no test coverage detected