OpenClaw 依赖注入:解耦组件提升可测试性

··
OpenClaw 技术团队
专注于 OpenClaw 小龙虾框架的技术研究与分享

什么是依赖注入
#

依赖注入(Dependency Injection, DI)是一种设计模式,通过外部传入依赖而不是内部创建,实现组件解耦。

为什么使用 DI
#

紧耦合的问题
#

1
2
3
4
5
6
// 紧耦合 - 难以测试和替换
class ChatService {
  constructor() {
    this.model = new GPT4Model(); // 硬编码依赖
  }
}

解耦后的好处
#

1
2
3
4
5
6
// 松耦合 - 灵活可测试
class ChatService {
  constructor(modelProvider) {
    this.model = modelProvider; // 外部注入
  }
}

OpenClaw 中的 DI 实现
#

服务容器
#

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
class Container {
  constructor() {
    this.services = new Map();
  }
  
  register(name, factory) {
    this.services.set(name, factory);
  }
  
  resolve(name) {
    const factory = this.services.get(name);
    return factory(this);
  }
}

// 注册服务
container.register('model', (c) => new OpenAIProvider());
container.register('memory', (c) => new RedisMemory());
container.register('session', (c) => 
  new SessionManager(c.resolve('model'), c.resolve('memory'))
);

构造函数注入
#

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
class SkillExecutor {
  constructor(modelProvider, memoryStore, logger) {
    this.model = modelProvider;
    this.memory = memoryStore;
    this.logger = logger;
  }
  
  async execute(skill, input) {
    this.logger.info(`Executing ${skill.name}`);
    // 使用注入的依赖
  }
}

测试优势
#

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
// 使用 Mock 对象测试
test('skill execution', async () => {
  const mockModel = { complete: jest.fn() };
  const mockMemory = { get: jest.fn() };
  const mockLogger = { info: jest.fn() };
  
  const executor = new SkillExecutor(
    mockModel, mockMemory, mockLogger
  );
  
  await executor.execute(skill, input);
  
  expect(mockModel.complete).toHaveBeenCalled();
});

总结
#

依赖注入让代码更灵活、更可测试,是构建高质量 OpenClaw 应用的关键技术。