C#中SOLID原则简介
\n在.NET生态系统中进行C#开发,不仅需要掌握语法,还需要具备设计灵活、可维护且可测试系统的能力。正是为此目的,SOLID原则应运而生——这是由罗伯特·马丁(鲍勃大叔)提出的面向对象编程的五项基本规则。
\nSOLID这个缩写词的含义如下:
\n- \n
- S — Single Responsibility Principle(单一职责原则) \n
- O — Open/Closed Principle(开闭原则) \n
- L — Liskov Substitution Principle(里氏替换原则) \n
- I — Interface Segregation Principle(接口隔离原则) \n
- D — Dependency Inversion Principle(依赖倒置原则) \n
在本文中,我们将通过C#示例逐一剖析每个原则的实际应用,展示违反这些原则会导致的问题,以及正确应用如何使代码更整洁。
\n\n1. 单一职责原则(SRP)
\n核心思想:一个类应该只有一个引起变化的原因。换句话说,每个类只负责一个明确定义的任务。
\n\nC#中违反SRP的示例
\n考虑一个典型的例子——OrderService类,它做了太多事情:
public class OrderService\n{\n public void ProcessOrder(Order order)\n {\n // 1. 保存到数据库\n SaveToDatabase(order);\n \n // 2. 发送邮件\n SendEmail(order.CustomerEmail, "订单已创建");\n \n // 3. 记录日志\n File.WriteAllText("log.txt", $"订单 {order.Id} 已处理");\n }\n \n private void SaveToDatabase(Order order) { /* ... */ }\n private void SendEmail(string email, string message) { /* ... */ }\n}\n问题:更改邮件发送逻辑或日志记录方式将导致OrderService类发生修改。这违反了SRP。
正确的SRP实现
\n将职责分离到不同的服务中:
\npublic class OrderProcessor\n{\n private readonly IOrderRepository _repository;\n private readonly INotificationService _notificationService;\n private readonly ILogger _logger;\n \n public OrderProcessor(\n IOrderRepository repository,\n INotificationService notificationService,\n ILogger logger)\n {\n _repository = repository;\n _notificationService = notificationService;\n _logger = logger;\n }\n \n public void ProcessOrder(Order order)\n {\n _repository.Save(order);\n _notificationService.SendConfirmation(order.CustomerEmail);\n _logger.Log($"订单 {order.Id} 已处理");\n }\n}\n\npublic interface IOrderRepository { void Save(Order order); }\npublic interface INotificationService { void SendConfirmation(string email); }\npublic interface ILogger { void Log(string message); }\n现在每个类只负责自己的任务。更改日志记录逻辑不会影响订单处理。
\n\n2. 开闭原则(OCP)
\n核心思想:类应该对扩展开放,对修改关闭。也就是说,你应该能够在不修改现有代码的情况下添加新行为。
\n\nC#中违反OCP的示例
\n经典例子——带有条件判断的计算器:
\npublic class AreaCalculator\n{\n public double CalculateArea(object shape)\n {\n if (shape is Rectangle rect)\n return rect.Width * rect.Height;\n else if (shape is Circle circle)\n return Math.PI * circle.Radius * circle.Radius;\n // 添加新图形需要修改此方法!\n throw new NotSupportedException();\n }\n}