TypeScript中的SOLID原则:从理论到实践全面解析
\n\nSOLID是罗伯特·马丁(Bob大叔)提出的面向对象编程五大基本原则的首字母缩写。这些原则有助于创建灵活、可维护且可扩展的代码。本文将结合TypeScript示例,从简单定义到实际使用场景,详细解析每个SOLID原则。
\n\n1. Single Responsibility Principle (SRP) — 单一职责原则
\n\n定义:每个类应该只有一个引起变化的原因。换句话说,一个类应该只负责一个明确定义的任务。
\n\n问题:当一个类承担多个职责时,测试、扩展和维护会变得困难。修改一个功能可能会破坏另一个功能。
\n\n违反SRP的示例:
\n// ❌ 违反SRP:该类同时负责存储、格式化和发送\nclass UserService {\n saveUser(user: User): void {\n // 保存到数据库\n console.log('User saved');\n }\n\n formatUserData(user: User): string {\n return `Name: ${user.name}, Email: ${user.email}`;\n }\n\n sendWelcomeEmail(user: User): void {\n // 发送邮件\n console.log('Email sent');\n }\n}\n\n遵循SRP的解决方案:
\n// ✅ 每个类负责自己的任务\nclass UserRepository {\n save(user: User): void {\n console.log('User saved');\n }\n}\n\nclass UserFormatter {\n format(user: User): string {\n return `Name: ${user.name}, Email: ${user.email}`;\n }\n}\n\nclass EmailService {\n sendWelcome(user: User): void {\n console.log('Email sent');\n }\n}\n\n2. Open-Closed Principle (OCP) — 开闭原则
\n\n定义:类应该对扩展开放,对修改关闭。这意味着你应该能够在不修改现有代码的情况下添加新功能。
\n\n违反OCP的示例:
\n// ❌ 添加新图形类型时,必须修改calculateArea方法\nclass AreaCalculator {\n calculateArea(shape: any): number {\n if (shape.type === 'circle') {\n return Math.PI * shape.radius ** 2;\n } else if (shape.type === 'rectangle') {\n return shape.width * shape.height;\n }\n throw new Error('Unknown shape');\n }\n}\n\n遵循OCP的解决方案(使用多态):
\n// ✅ 使用接口和继承\ninterface Shape {\n area(): number;\n}\n\nclass Circle implements Shape {\n constructor(private radius: number) {}\n area(): number {\n return Math.PI * this.radius ** 2;\n }\n}\n\nclass Rectangle implements Shape {\n constructor(private width: number, private height: number) {}\n area(): number {\n return this.width * this.height;\n }\n}\n\nclass AreaCalculator {\n calculateArea(shape: Shape): number {\n return shape.area(); // 添加新图形时无需修改\n }\n}\n\n3. Liskov Substitution Principle (LSP) — 里氏替换原则
\n\n定义:程序中的对象应该可以被其子类型的实例替换,而不影响程序的正确性。子类不应违反父类的约定。
\n\n违反LSP的示例:
\n// ❌ 违反原则:子类改变了父类的行为\nclass Bird {\n fly(): void {\n console.log('Flying');\n }\n}\n\nclass Penguin extends Bird {\n fly(): void {\n throw new Error('Penguins cannot fly!'); // 违反约定\n }\n}\n\n遵循LSP的解决方案:
\n// ✅ 分