工厂函数组合Skill factory-function-composition

工厂函数组合技能专注于在TypeScript中应用工厂函数模式,实现干净的依赖注入和函数组合,通过分离客户端、服务和方法的配置提高代码的可测试性、可重用性和灵活性,适用于软件开发架构设计。关键词:工厂函数、依赖注入、函数组合、TypeScript、设计模式、可测试代码。

架构设计 0 次安装 0 次浏览 更新于 3/20/2026

名称: 工厂函数组合 描述: 应用工厂函数模式来组合客户端和服务,实现适当的关注点分离。当创建依赖于外部客户端的函数、用特定领域方法包装资源或重构将客户端/服务/方法选项混合在一起的代码时使用。 元数据: 作者: epicenter 版本: ‘1.0’

工厂函数组合

这个技能帮助您在TypeScript中应用工厂函数模式,实现干净的依赖注入和函数组合。

何时应用此技能

当您看到以下情况时使用此模式:

  • 一个函数以客户端/资源作为第一个参数
  • 不同层(客户端、服务、方法)的选项混合在一起
  • 客户端创建发生在不应该拥有它的函数内部
  • 函数难以测试,因为它们创建自己的依赖项

通用签名

每个工厂函数都遵循此签名:

function createSomething(dependencies, options?) {
	return {
		/* methods */
	};
}
  • 第一个参数:总是资源。要么是单个客户端,要么是解构的多个依赖对象。
  • 第二个参数:可选的特定于此工厂的配置。永远不是客户端配置——那属于客户端创建时。

最多两个参数。第一个是资源,第二个是配置。没有例外。

核心模式

// 单个依赖
function createService(client, options = {}) {
	return {
		method(methodOptions) {
			// 使用client、options和methodOptions
		},
	};
}

// 多个依赖
function createService({ db, cache }, options = {}) {
	return {
		method(methodOptions) {
			// 使用db、cache、options和methodOptions
		},
	};
}

// 使用示例
const client = createClient(clientOptions);
const service = createService(client, serviceOptions);
service.method(methodOptions);

关键原则

  1. 客户端配置属于客户端创建时 — 不要通过工厂传递clientOptions
  2. 每个层都有自己的选项 — 客户端、服务和方法的选项保持分离
  3. 依赖项优先 — 工厂函数以依赖项作为第一个参数
  4. 返回带有方法的对象 — 不是需要传递资源的独立函数

识别反模式

反模式 1: 函数以客户端作为第一个参数

// 不良做法
function doSomething(client, options) { ... }
doSomething(client, options);

// 良好做法
const service = createService(client);
service.doSomething(options);

反模式 2: 客户端创建隐藏内部

// 不良做法
function doSomething(clientOptions, methodOptions) {
	const client = createClient(clientOptions); // 隐藏!
	// ...
}

// 良好做法
const client = createClient(clientOptions);
const service = createService(client);
service.doSomething(methodOptions);

反模式 3: 混合选项块

// 不良做法
doSomething({
	timeout: 5000, // 客户端选项
	retries: 3, // 客户端选项
	endpoint: '/users', // 方法选项
	payload: data, // 方法选项
});

// 良好做法
const client = createClient({ timeout: 5000, retries: 3 });
const service = createService(client);
service.doSomething({ endpoint: '/users', payload: data });

反模式 4: 多层隐藏

// 不良做法
function doSomething(clientOptions, serviceOptions, methodOptions) {
	const client = createClient(clientOptions);
	const service = createService(client, serviceOptions);
	return service.method(methodOptions);
}

// 良好做法 — 每层可见且可配置
const client = createClient(clientOptions);
const service = createService(client, serviceOptions);
service.method(methodOptions);

多个依赖项

当您的服务需要多个客户端时:

function createService(
	{ db, cache, http }, // 依赖项作为解构对象
	options = {}, // 服务选项
) {
	return {
		method(methodOptions) {
			// 使用db、cache、http
		},
	};
}

// 使用示例
const db = createDbConnection(dbOptions);
const cache = createCacheClient(cacheOptions);
const http = createHttpClient(httpOptions);

const service = createService({ db, cache, http }, serviceOptions);
service.method(methodOptions);

心智模型

将其视为一个链条,其中每个链接:

  • 从前一个链接接收资源
  • 添加自己的配置
  • 为下一个链接产生某些东西
createClient(...)  →  createService(client, ...)  →  service.method(...)
     ↑                       ↑                            ↑
 clientOptions          serviceOptions              methodOptions

优势

  • 可测试性:轻松注入模拟客户端
  • 可重用性:在多个服务之间共享客户端
  • 灵活性:独立配置每个层
  • 清晰性:每个级别配置的明确所有权

参考文献

查看完整文章了解更多详情: