Java中的SOLID原则:从理论到实践
\n\nSOLID是罗伯特·马丁(Bob大叔)提出的面向对象编程的五个基本原则的首字母缩写。这些原则有助于创建灵活、可维护且可扩展的代码。在本文中,我们将通过Java示例逐一分析每个原则,展示如何违反它们,以及如何正确应用。
\n\n为什么需要SOLID原则?
\n没有SOLID,代码很快就会变成“意大利面条”。你是否遇到过修改一个类却破坏了其他三个类的情况?或者一个方法做了太多事情?SOLID解决了这些问题。每个原则都是一条规则,使代码:
\n- \n
- 对变更具有弹性——新需求不会破坏旧逻辑。 \n
- 易于理解——每个类只负责一件事。 \n
- 可测试——易于编写单元测试。 \n
1. 单一职责原则 (SRP)
\n定义:“一个类应该只有一个引起它变化的原因”。
\n简单来说:一个类应该只做一件事。如果一个类有多个职责,就很难维护。
\n\n违反SRP(糟糕的代码)
\npublic class OrderService {\n public void createOrder(Order order) {\n // 创建订单的逻辑\n saveToDatabase(order);\n sendEmailConfirmation(order);\n }\n\n private void saveToDatabase(Order order) {\n // 保存到数据库\n }\n\n private void sendEmailConfirmation(Order order) {\n // 发送邮件\n }\n}\n问题:该类同时负责业务逻辑、数据库操作和发送通知。修改邮件服务将需要修改OrderService。
正确的SRP实现
\npublic class OrderService {\n private final OrderRepository repository;\n private final EmailService emailService;\n\n public OrderService(OrderRepository repo, EmailService email) {\n this.repository = repo;\n this.emailService = email;\n }\n\n public void createOrder(Order order) {\n repository.save(order);\n emailService.sendConfirmation(order);\n }\n}\n\npublic class OrderRepository {\n public void save(Order order) { /* 数据库逻辑 */ }\n}\n\npublic class EmailService {\n public void sendConfirmation(Order order) { /* 邮件逻辑 */ }\n}\n现在每个类只有一个变更原因。OrderService仅在创建订单的业务流程发生变化时才需要修改。
2. 开闭原则 (OCP)
\n定义:“类应该对扩展开放,对修改关闭”。
\n这意味着你应该通过新代码添加新功能,而不是修改现有代码。
\n\n违反OCP(糟糕的代码)
\npublic class AreaCalculator {\n public double calculateArea(Object shape) {\n if (shape instanceof Rectangle) {\n Rectangle r = (Rectangle) shape;\n return r.width * r.height;\n } else if (shape instanceof Circle) {\n Circle c = (Circle) shape;\n return Math.PI * c.radius * c.radius;\n }\n throw new IllegalArgumentException("未知形状");\n }\n}\n要添加三角形,需要修改calculateArea方法——这违反了OCP。
正确的OCP实现
\npublic interface Shape {\n double calculateArea();\n}\n\npublic class Rectangle implements Shape {\n private double width, height;\n public Rectangle(double w, double h) { this.width = w; this.height = h; }\n @Override\n public double calculateArea() { return width * height; }\n}\n\npublic class Circle implements Shape {\n private double radius;\n