在构建 NestJS 应用时,合理的数据处理模式和架构设计至关重要。本文将介绍除了常见的 DTO 模式外,其他核心的设计模式和概念,帮助你构建更优雅的应用程序。
// user.bo.ts
export class UserBO {
constructor(private readonly user: User) {}
async promoteToVIP(): Promise<void> {
if (this.canBePromoted()) {
this.user.role = 'VIP';
this.user.promotedAt = new Date();
}
throw new BusinessError('User cannot be promoted');
}
private canBePromoted(): boolean {
return this.user.purchaseAmount > 1000;
}
}
// money.vo.ts
export class Money {
private constructor(
private readonly amount: number,
private readonly currency: string
) {}
static of(amount: number, currency: string): Money {
return new Money(amount, currency);
}
add(other: Money): Money {
if (this.currency !== other.currency) {
throw new Error('Cannot add different currencies');
}
return new Money(this.amount + other.amount, this.currency);
}
}
// user.request.ts
export class CreateUserRequest {
readonly username: string;
readonly email: string;
readonly password: string;
validate(): void {
// 验证逻辑
}
}
// api.response.ts
export class ApiResponse<T> {
constructor(
public readonly success: boolean,
public readonly data?: T,
public readonly error?: string
) {}
static success<T>(data: T): ApiResponse<T> {
return new ApiResponse(true, data);
}
static error<T>(message: string): ApiResponse<T> {
return new ApiResponse(false, undefined, message);
}
}
// database.config.ts
export const databaseConfig = {
command: {
type: 'mysql',
host: 'master-db.example.com',
// ... 主库配置
},
query: {
type: 'mongodb', // 可以使用不同类型数据库
host: 'replica-db.example.com',
// ... 从库配置
}
};
// user.command.ts
@CommandHandler(CreateUserCommand)
export class CreateUserHandler {
constructor(
@InjectRepository(User, 'command') // 注入主库连接
private userRepo: Repository<User>
) {}
async execute(command: CreateUserCommand): Promise<void> {
// 写操作使用主库
await this.userRepo.save(command.user);
}
}
// user.query.ts
@QueryHandler(GetUserQuery)
export class GetUserHandler {
constructor(
@InjectRepository(User, 'query') // 注入从库连接
private userRepo: Repository<User>
) {}
async execute(query: GetUserQuery): Promise<UserDTO> {
// 读操作使用从库
return this.userRepo.findOne(query.id);
}
}
// event-sourcing.service.ts
@Injectable()
export class EventSourcingService {
constructor(
private eventStore: EventStore,
private readonly queryDb: QueryDatabase
) {}
async publishEvent(event: DomainEvent): Promise<void> {
// 1. 保存事件到事件存储
await this.eventStore.save(event);
// 2. 更新查询数据库
await this.queryDb.handleEvent(event);
}
}
// user.command.ts
@CommandHandler(CreateUserCommand)
export class CreateUserHandler {
constructor(
private eventSourcing: EventSourcingService
) {}
async execute(command: CreateUserCommand): Promise<void> {
// 创建用户事件
const event = new UserCreatedEvent(command.user);
// 发布事件进行数据同步
await this.eventSourcing.publishEvent(event);
}
}
适用场景:
性能优势:
架构优势:
// validation.pipe.ts
@Injectable()
export class CustomValidationPipe implements PipeTransform {
transform(value: any, metadata: ArgumentMetadata) {
// 自定义验证逻辑
return value;
}
}
// logging.interceptor.ts
@Injectable()
export class LoggingInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const now = Date.now();
return next.handle().pipe(
tap(() => console.log(`Request took ${Date.now() - now}ms`))
);
}
}