引言:为什么SOLID在TypeScript中很重要
SOLID是罗伯特·马丁(Bob大叔)提出的五个面向对象设计基本原则的首字母缩写。在TypeScript的上下文中,这些原则因其严格的类型系统和对现代OOP范式的支持而具有特殊价值。应用SOLID原则能使代码更加灵活、可测试且易于维护,这对可扩展项目至关重要。
在本文中,我们将通过TypeScript的实际示例来解析每个SOLID原则,展示反模式及其正确实现。您将学习如何编写在添加新功能时不会出错的代码。
1. Single Responsibility Principle (SRP) — 单一职责原则
理论
每个类应该只有一个引起变化的原因。这意味着一个类应该只负责程序功能的一个部分。如果一个类执行多个任务,它将更难维护和测试。
反模式(违反SRP)
class UserService { saveUser(user: User): void { // 保存到数据库 console.log('User saved'); }
sendEmail(user: User, message: string): void { // 发送邮件 console.log(`Email sent to ${user.email}`); }
generateReport(user: User): string { // 生成报告 return `Report for ${user.name}`; }}正确实现(SRP)
class UserRepository { save(user: User): void { // 仅保存 }}
class EmailService { send(user: User, message: string): void { // 仅发送邮件 }}
class ReportGenerator { generate(user: User): string { // 仅生成报告 }}2. Open-Closed Principle (OCP) — 开闭原则
理论
类应该对扩展开放,对修改关闭。新功能应通过继承或组合来添加,而不是修改现有代码。
反模式(违反OCP)
class PaymentProcessor { processPayment(type: string, amount: number): void { if (type === 'card') { // 处理信用卡 } else if (type === 'paypal') { // 处理PayPal } else if (type === 'crypto') { // 处理加密货币 } // 添加新类型时——需要修改类! }}正确实现(OCP)
interface PaymentMethod { process(amount: number): void;}
class CardPayment implements PaymentMethod { process(amount: number): void { console.log(`Processing card payment: $${amount}`); }}
class PayPalPayment implements PaymentMethod { process(amount: number): void { console.log(`Processing PayPal payment: $${amount}`); }}
class PaymentProcessor { constructor(private paymentMethod: PaymentMethod) {}
process(amount: number): void { this.paymentMethod.process(amount); }}3. Liskov Substitution Principle (LSP) — 里氏替换原则
理论
基类对象应能被其子类对象替换,而不影响程序的正确性。子类不应改变基类的预期行为。
反模式(违反LSP)
class Rectangle { constructor(public width: number, public height: number) {}
setWidth(width: number): void { this.width = width; }
setHeight(height: number): void { this.height = height; }
getArea(): number { return this.width * this.height; }}
class Square extends Rectangle {