[ PROMPT_NODE_23768 ]
服务与仓库层
[ SKILL_DOCUMENTATION ]
# 服务与仓库 - 业务逻辑层
组织业务逻辑(服务)与数据访问(仓库)的完整指南。
## 目录
- [服务层概述](#service-layer-overview)
- [依赖注入模式](#dependency-injection-pattern)
- [单例模式](#singleton-pattern)
- [仓库模式](#repository-pattern)
- [服务设计原则](#service-design-principles)
- [缓存策略](#caching-strategies)
- [测试服务](#testing-services)
---
## 服务层概述
### 服务的作用
**服务包含业务逻辑** - 应用程序的“是什么”和“为什么”:
控制器询问:“我应该这样做吗?”
服务回答:“是/否,原因如下,以及接下来会发生什么”
仓库执行:“这是你请求的数据”
**服务负责:**
- ✅ 业务规则执行
- ✅ 编排多个仓库
- ✅ 事务管理
- ✅ 复杂计算
- ✅ 外部服务集成
- ✅ 业务验证
**服务不应该:**
- ❌ 了解 HTTP(请求/响应)
- ❌ 直接访问 Prisma(使用仓库)
- ❌ 处理路由特定的逻辑
- ❌ 格式化 HTTP 响应
---
## 依赖注入模式
### 为什么使用依赖注入?
**优势:**
- 易于测试(注入模拟对象)
- 清晰的依赖关系
- 灵活的配置
- 促进松耦合
### 优秀示例:NotificationService
**文件:** `/blog-api/src/services/NotificationService.ts`
typescript
// 定义依赖接口以保持清晰
export interface NotificationServiceDependencies {
prisma: PrismaClient;
batchingService: BatchingService;
emailComposer: EmailComposer;
}
// 带有依赖注入的服务
export class NotificationService {
private prisma: PrismaClient;
private batchingService: BatchingService;
private emailComposer: EmailComposer;
private preferencesCache: Map = new Map();
private CACHE_TTL = (notificationConfig.preferenceCacheTTLMinutes || 5) * 60 * 1000;
// 通过构造函数注入依赖
constructor(dependencies: NotificationServiceDependencies) {
this.prisma = dependencies.prisma;
this.batchingService = dependencies.batchingService;
this.emailComposer = dependencies.emailComposer;
}
/**
* 创建通知并进行适当的路由
*/
async createNotification(params: CreateNotificationParams)