SOLID原则深度解析:面向对象设计的五大基石

SOLID原则深度解析:面向对象设计的五大基石

标签:SOLID 面向对象设计 设计原则 代码质量 软件架构 重构

摘要:本文从Robert C. Martin提出的SOLID原则出发,深入剖析单一职责、开闭、里氏替换、接口隔离、依赖倒置五大原则,结合JDK、Spring源码与生产代码示例,揭示如何写出高内聚、低耦合、易维护的代码。


一、SOLID原则概览

复制代码
┌─────────────────────────────────────────────────────────┐
│  SOLID:面向对象设计的五大原则                              │
│  ─────────────────────────────────────────────────────  │
│                                                          │
│  S - Single Responsibility Principle(单一职责原则)       │
│     └─ 一个类只应有一个引起变化的原因                      │
│                                                          │
│  O - Open/Closed Principle(开闭原则)                     │
│     └─ 对扩展开放,对修改关闭                              │
│                                                          │
│  L - Liskov Substitution Principle(里氏替换原则)          │
│     └─ 子类必须能够替换父类                                │
│                                                          │
│  I - Interface Segregation Principle(接口隔离原则)        │
│     └─ 客户端不应依赖它不需要的接口                         │
│                                                          │
│  D - Dependency Inversion Principle(依赖倒置原则)         │
│     └─ 依赖抽象,而非具体实现                               │
│                                                          │
│  ═══════════════════════════════════════════════════     │
│  共同目标:                                                │
│  • 高内聚:相关功能集中,无关功能分离                        │
│  • 低耦合:模块间依赖最小化                                  │
│  • 易维护:修改一处不影响全局                                │
│  • 可测试:单元测试友好                                      │
│  • 可扩展:新功能通过增加代码实现                            │
└─────────────────────────────────────────────────────────┘

二、S - 单一职责原则(Single Responsibility Principle)

2.1 原则定义

一个类应该只有一个引起它变化的原因。

There should never be more than one reason for a class to change.

复制代码
┌─────────────────────────────────────────────────────────┐
│  违反SRP:上帝类(God Class)                               │
├─────────────────────────────────────────────────────────┤
│                                                          │
│  public class OrderManager {                             │
│      // 订单CRUD                                          │
│      public void createOrder() { ... }                   │
│      public void updateOrder() { ... }                   │
│      public void deleteOrder() { ... }                   │
│                                                          │
│      // 支付处理                                          │
│      public void processPayment() { ... }                │
│      public void refund() { ... }                        │
│                                                          │
│      // 库存管理                                          │
│      public void deductInventory() { ... }               │
│      public void releaseInventory() { ... }              │
│                                                          │
│      // 物流跟踪                                          │
│      public void shipOrder() { ... }                     │
│      public void trackShipment() { ... }                 │
│                                                          │
│      // 报表生成                                          │
│      public void generateInvoice() { ... }               │
│      public void exportToExcel() { ... }                 │
│  }                                                       │
│                                                          │
│  问题:                                                    │
│  • 6个变化原因 → 6个部门可能要求修改                       │
│  • 500+行代码,难以理解和维护                              │
│  • 修改支付逻辑可能影响订单CRUD                            │
│  • 单元测试需要Mock所有依赖                                │
│                                                          │
└─────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────┐
│  遵循SRP:职责分离                                         │
├─────────────────────────────────────────────────────────┤
│                                                          │
│  ┌─────────────────┐  ┌─────────────────┐               │
│  │  OrderService   │  │ PaymentService  │               │
│  │  (订单生命周期) │  │ (支付处理)     │               │
│  │                 │  │                 │               │
│  │  createOrder()  │  │ process()       │               │
│  │  cancelOrder()  │  │ refund()        │               │
│  │  queryOrder()   │  │ queryStatus()   │               │
│  └─────────────────┘  └─────────────────┘               │
│                                                          │
│  ┌─────────────────┐  ┌─────────────────┐               │
│  │ InventoryService│  │ ShippingService │               │
│  │ (库存管理)      │  │ (物流管理)     │               │
│  │                 │  │                 │               │
│  │ reserve()       │  │ ship()          │               │
│  │ release()       │  │ track()         │               │
│  │ queryStock()    │  │ updateStatus()  │               │
│  └─────────────────┘  └─────────────────┘               │
│                                                          │
│  ┌─────────────────┐                                    │
│  │ ReportService   │                                    │
│  │ (报表生成)      │                                    │
│  │                 │                                    │
│  │ generateInvoice()│                                    │
│  │ exportExcel()   │                                    │
│  └─────────────────┘                                    │
│                                                          │
│  收益:                                                    │
│  • 每个类 < 100行代码,职责清晰                            │
│  • 修改支付不影响订单查询                                   │
│  • 可独立测试、部署、扩展                                   │
│                                                          │
└─────────────────────────────────────────────────────────┘

2.2 识别职责的启发式规则

信号 说明 解决方案
类名含"And"/"Or" OrderAndPaymentManager 拆分为OrderService + PaymentService
方法分组操作不同数据 一半方法操作Order,一半操作Payment 按数据边界拆分
大量私有方法 某些方法只被特定方法调用 提取为独立类
频繁导入不同包 同时导入order, payment, inventory 按包边界拆分
注释标记不同章节 // ===== Payment Methods ===== 章节即职责边界

2.3 Spring源码中的SRP

java 复制代码
/**
 * Spring的BeanFactory体系:职责分离典范
 */

// 职责1:Bean的注册
public interface BeanDefinitionRegistry {
    void registerBeanDefinition(String beanName, BeanDefinition beanDefinition);
    void removeBeanDefinition(String beanName);
    boolean containsBeanDefinition(String beanName);
}

// 职责2:Bean的获取
public interface BeanFactory {
    Object getBean(String name);
    <T> T getBean(String name, Class<T> requiredType);
    boolean containsBean(String name);
}

// 职责3:Bean的配置(继承前两者)
public interface ConfigurableListableBeanFactory 
    extends ListableBeanFactory, AutowireCapableBeanFactory, 
            ConfigurableBeanFactory, BeanDefinitionRegistry {
    // 配置相关方法
}

// 职责4:Bean的创建(内部使用)
abstract class AbstractAutowireCapableBeanFactory 
    extends AbstractBeanFactory
    implements AutowireCapableBeanFactory {
    
    // 只负责Bean的创建、属性注入、初始化
    protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args);
    protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw);
    protected Object initializeBean(String beanName, Object bean, RootBeanDefinition mbd);
}

三、O - 开闭原则(Open/Closed Principle)

3.1 原则定义

软件实体应该对扩展开放,对修改关闭。

Software entities should be open for extension, but closed for modification.

复制代码
┌─────────────────────────────────────────────────────────┐
│  违反OCP:if-else地狱                                       │
├─────────────────────────────────────────────────────────┤
│                                                          │
│  public class PaymentProcessor {                         │
│                                                          │
│      public void process(String type, PaymentRequest req) {│
│          if ("ALIPAY".equals(type)) {                    │
│              // 20行支付宝逻辑                             │
│              callAlipayApi(req);                         │
│              saveAlipayResult(req);                      │
│          } else if ("WECHAT".equals(type)) {             │
│              // 20行微信逻辑                               │
│              callWechatApi(req);                         │
│              saveWechatResult(req);                      │
│          } else if ("UNIONPAY".equals(type)) {           │
│              // 20行银联逻辑                               │
│              callUnionApi(req);                          │
│              saveUnionResult(req);                       │
│          }                                               │
│          // 每增加一种支付方式,修改此类                     │
│      }                                                   │
│  }                                                       │
│                                                          │
│  问题:                                                    │
│  • 修改现有代码 → 引入Bug风险                              │
│  • 类不断增长 → 难以维护                                   │
│  • 违反SRP:多种支付逻辑混杂                               │
│  • 无法单元测试单独支付方式                                │
│                                                          │
└─────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────┐
│  遵循OCP:策略模式扩展                                     │
├─────────────────────────────────────────────────────────┤
│                                                          │
│  // 1. 抽象策略接口(封闭修改)                             │
│  public interface PaymentStrategy {                      │
│      boolean supports(PaymentType type);                 │
│      PaymentResult process(PaymentRequest request);      │
│  }                                                       │
│                                                          │
│  // 2. 具体策略(开放扩展)                                 │
│  @Component                                              │
│  public class AlipayStrategy implements PaymentStrategy {│
│      public boolean supports(PaymentType type) {         │
│          return type == PaymentType.ALIPAY;              │
│      }                                                   │
│      public PaymentResult process(PaymentRequest req) {  │
│          // 支付宝特定逻辑                                 │
│      }                                                   │
│  }                                                       │
│                                                          │
│  @Component                                              │
│  public class WechatStrategy implements PaymentStrategy {│
│      // 微信实现...                                        │
│  }                                                       │
│                                                          │
│  // 3. 上下文(稳定,无需修改)                              │
│  @Service                                                │
│  public class PaymentProcessor {                         │
│      private final List<PaymentStrategy> strategies;     │
│                                                          │
│      public PaymentProcessor(List<PaymentStrategy> strategies) {│
│          this.strategies = strategies;                   │
│      }                                                   │
│                                                          │
│      public PaymentResult process(PaymentType type,      │
│                                   PaymentRequest req) {  │
│          return strategies.stream()                      │
│              .filter(s -> s.supports(type))              │
│              .findFirst()                                │
│              .orElseThrow(() -> new UnsupportedPaymentException(type))│
│              .process(req);                              │
│      }                                                   │
│  }                                                       │
│                                                          │
│  新增支付方式:创建新类实现PaymentStrategy,零修改现有代码      │
│                                                          │
└─────────────────────────────────────────────────────────┘

3.2 Spring的扩展机制(OCP典范)

java 复制代码
/**
 * Spring的BeanPostProcessor:对扩展开放
 * 用户无需修改Spring源码,即可扩展Bean创建过程
 */

// Spring核心(封闭修改)
public abstract class AbstractAutowireCapableBeanFactory {
    
    public Object applyBeanPostProcessorsBeforeInitialization(
            Object existingBean, String beanName) {
        
        Object result = existingBean;
        // 遍历所有注册的处理器(开放扩展点)
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            Object current = processor.postProcessBeforeInitialization(result, beanName);
            if (current == null) {
                return result;
            }
            result = current;
        }
        return result;
    }
}

// 用户扩展(开放扩展)
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        // 自定义初始化逻辑,无需修改Spring
        if (bean instanceof MyService) {
            ((MyService) bean).customInit();
        }
        return bean;
    }
}

四、L - 里氏替换原则(Liskov Substitution Principle)

4.1 原则定义

子类型必须能够替换其基类型。

Subtypes must be substitutable for their base types.

Barbara Liskov, 1987

复制代码
┌─────────────────────────────────────────────────────────┐
│  违反LSP:正方形继承长方形(经典反例)                        │
├─────────────────────────────────────────────────────────┤
│                                                          │
│  class Rectangle {                                       │
│      protected int width;                                │
│      protected int height;                               │
│                                                          │
│      public void setWidth(int width) { this.width = width; }│
│      public void setHeight(int height) { this.height = height; }│
│      public int getArea() { return width * height; }     │
│  }                                                       │
│                                                          │
│  class Square extends Rectangle {                        │
│      @Override                                           │
│      public void setWidth(int width) {                   │
│          this.width = width;                             │
│          this.height = width; // 正方形宽高相等             │
│      }                                                   │
│                                                          │
│      @Override                                           │
│      public void setHeight(int height) {                 │
│          this.height = height;                           │
│          this.width = height; // 正方形宽高相等             │
│      }                                                   │
│  }                                                       │
│                                                          │
│  // 使用方                                               │
│  void resizeToArea(Rectangle r, int area) {              │
│      r.setWidth(area / 10);                              │
│      r.setHeight(10);                                    │
│      assert r.getArea() == area; // 对Square失败!        │
│  }                                                       │
│                                                          │
│  问题:Square无法替换Rectangle,破坏了使用方的预期            │
│                                                          │
└─────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────┐
│  遵循LSP:组合优于继承,或重新设计继承体系                     │
├─────────────────────────────────────────────────────────┤
│                                                          │
│  // 方案1:提取共同接口,放弃继承                            │
│  interface Shape {                                       │
│      int getArea();                                      │
│  }                                                       │
│                                                          │
│  class Rectangle implements Shape {                      │
│      private int width;                                  │
│      private int height;                                 │
│      // 各自独立setter,无继承约束                          │
│  }                                                       │
│                                                          │
│  class Square implements Shape {                         │
│      private int side;                                   │
│      // 只有setSide(),无width/height概念                   │
│  }                                                       │
│                                                          │
│  // 方案2:不可变对象(推荐)                                │
│  class Rectangle {                                       │
│      private final int width;                            │
│      private final int height;                           │
│                                                          │
│      public Rectangle(int width, int height) {           │
│          this.width = width;                             │
│          this.height = height;                           │
│      }                                                   │
│      // 无setter,自然满足LSP                              │
│  }                                                       │
│                                                          │
└─────────────────────────────────────────────────────────┘

4.2 LSP契约规则

契约类型 规则 违反示例
前置条件 子类不能强化前置条件 父类接受null,子类抛NPE
后置条件 子类不能弱化后置条件 父类承诺返回非null,子类返回null
不变式 子类必须保持父类不变式 父类size >= 0,子类允许负数
历史约束 子类方法不能允许父类禁止的状态变化 父类不可变,子类添加setter

4.3 JDK中的LSP

java 复制代码
/**
 * Java集合框架:LSP的完美实践
 */

// 基类定义契约
public abstract class AbstractList<E> extends AbstractCollection<E> 
    implements List<E> {
    
    public boolean add(E e) {  // 默认实现,子类可覆盖
        add(size(), e);
        return true;
    }
    
    public abstract E get(int index);  // 强制子类实现
}

// 子类1:ArrayList - 基于数组,支持随机访问
public class ArrayList<E> extends AbstractList<E> {
    public E get(int index) { 
        rangeCheck(index);
        return elementData(index);  // O(1)
    }
    // 满足LSP:get()行为符合List契约
}

// 子类2:LinkedList - 基于链表,顺序访问
public class LinkedList<E> extends AbstractSequentialList<E> {
    public E get(int index) {
        checkElementIndex(index);
        return node(index).item;  // O(n),但行为一致
    }
    // 满足LSP:虽然性能不同,但语义一致
}

// 使用方:无需关心具体实现
void printAll(List<String> list) {  // 接受任何List实现
    for (String s : list) {
        System.out.println(s);
    }
}
// ArrayList和LinkedList可无缝替换

五、I - 接口隔离原则(Interface Segregation Principle)

5.1 原则定义

客户端不应被迫依赖它们不使用的方法。

Clients should not be forced to depend on methods they do not use.

复制代码
┌─────────────────────────────────────────────────────────┐
│  违反ISP:胖接口(Fat Interface)                           │
├─────────────────────────────────────────────────────────┤
│                                                          │
│  public interface Worker {                               │
│      void work();                                        │
│      void eat();                                         │
│      void sleep();                                       │
│      void attendMeeting();                               │
│      void submitReport();                                │
│      void manageTeam();    // 只有经理需要                  │
│      void writeCode();     // 只有程序员需要                │
│      void designUI();      // 只有设计师需要                │
│  }                                                       │
│                                                          │
│  public class Programmer implements Worker {             │
│      public void work() { writeCode(); }                 │
│      public void eat() { ... }                           │
│      public void sleep() { ... }                         │
│      public void attendMeeting() { ... }                 │
│      public void submitReport() { ... }                  │
│      public void manageTeam() {                          │
│          throw new UnsupportedOperationException();      │
│      }  // 被迫实现不需要的方法                             │
│      public void designUI() {                            │
│          throw new UnsupportedOperationException();      │
│      }  // 被迫实现不需要的方法                             │
│  }                                                       │
│                                                          │
│  问题:                                                    │
│  • Programmer依赖了manageTeam()和designUI()               │
│  • 接口变更影响所有实现类                                   │
│  • 无法部分复用接口                                        │
│                                                          │
└─────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────┐
│  遵循ISP:接口拆分                                         │
├─────────────────────────────────────────────────────────┤
│                                                          │
│  // 基础能力                                               │
│  public interface Workable {                             │
│      void work();                                        │
│  }                                                       │
│                                                          │
│  public interface Living {                               │
│      void eat();                                         │
│      void sleep();                                       │
│  }                                                       │
│                                                          │
│  public interface MeetingAttendee {                      │
│      void attendMeeting();                               │
│  }                                                       │
│                                                          │
│  // 专业能力                                               │
│  public interface Coder extends Workable {               │
│      void writeCode();                                   │
│      void reviewCode();                                  │
│  }                                                       │
│                                                          │
│  public interface Manager extends Workable, MeetingAttendee {│
│      void manageTeam();                                  │
│      void evaluatePerformance();                         │
│  }                                                       │
│                                                          │
│  public interface Designer extends Workable {            │
│      void designUI();                                    │
│      void createPrototype();                             │
│  }                                                       │
│                                                          │
│  // 实现类只依赖需要的接口                                   │
│  public class Programmer implements Coder, Living, MeetingAttendee {│
│      // 只实现相关方法,无被迫实现的空方法                     │
│  }                                                       │
│                                                          │
│  public class TechLead implements Coder, Manager, Living {│
│      // 技术经理:编码 + 管理                                │
│  }                                                       │
│                                                          │
└─────────────────────────────────────────────────────────┘

5.2 Spring的接口设计(ISP典范)

java 复制代码
/**
 * Spring的Environment接口:细粒度拆分
 */

// 只读访问
public interface PropertyResolver {
    String getProperty(String key);
    <T> T getProperty(String key, Class<T> targetType);
    boolean containsProperty(String key);
}

// 可配置
public interface ConfigurablePropertyResolver extends PropertyResolver {
    void setRequiredProperties(String... requiredProperties);
    void validateRequiredProperties() throws MissingRequiredPropertiesException;
    void setConversionService(ConfigurableConversionService conversionService);
}

// 配置文件源
public interface Environment extends PropertyResolver {
    String[] getActiveProfiles();
    String[] getDefaultProfiles();
    boolean acceptsProfiles(Profiles profiles);
}

// 可配置环境
public interface ConfigurableEnvironment extends Environment, ConfigurablePropertyResolver {
    void setActiveProfiles(String... profiles);
    void addActiveProfile(String profile);
    MutablePropertySources getPropertySources();
}

// 使用方按需依赖
@Component
public class MyService {
    
    // 只需要读取配置,不需要修改
    public MyService(PropertyResolver propertyResolver) {
        String value = propertyResolver.getProperty("my.key");
    }
}

六、D - 依赖倒置原则(Dependency Inversion Principle)

6.1 原则定义

高层模块不应依赖低层模块,两者都应依赖抽象。
抽象不应依赖细节,细节应依赖抽象。

High-level modules should not depend on low-level modules. Both should depend on abstractions.
Abstractions should not depend on details. Details should depend on abstractions.

复制代码
┌─────────────────────────────────────────────────────────┐
│  违反DIP:高层依赖低层具体实现                               │
├─────────────────────────────────────────────────────────┤
│                                                          │
│  // 低层:数据访问                                          │
│  public class MySqlOrderRepository {                     │
│      public Order findById(Long id) {                    │
│          // JDBC代码,直接依赖MySQL                        │
│      }                                                   │
│  }                                                       │
│                                                          │
│  // 高层:业务逻辑                                          │
│  public class OrderService {                             │
│      private MySqlOrderRepository repository =            │
│          new MySqlOrderRepository();  // 直接依赖具体类!    │
│                                                          │
│      public Order getOrder(Long id) {                    │
│          return repository.findById(id);                 │
│      }                                                   │
│  }                                                       │
│                                                          │
│  问题:                                                    │
│  • OrderService无法脱离MySQL测试                           │
│  • 更换数据库需要修改OrderService                          │
│  • 无法使用Mock进行单元测试                                │
│                                                          │
└─────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────┐
│  遵循DIP:依赖抽象                                          │
├─────────────────────────────────────────────────────────┤
│                                                          │
│  // 抽象:由高层定义,低层实现                               │
│  public interface OrderRepository {                      │
│      Optional<Order> findById(OrderId id);               │
│      Order save(Order order);                            │
│  }                                                       │
│                                                          │
│  // 高层:只依赖抽象                                        │
│  public class OrderService {                             │
│      private final OrderRepository repository;           │
│                                                          │
│      // 依赖注入抽象                                        │
│      public OrderService(OrderRepository repository) {   │
│          this.repository = repository;                   │
│      }                                                   │
│                                                          │
│      public Order getOrder(OrderId id) {                 │
│          return repository.findById(id)                  │
│              .orElseThrow(() -> new OrderNotFoundException(id));│
│      }                                                   │
│  }                                                       │
│                                                          │
│  // 低层:实现抽象                                          │
│  @Repository                                             │
│  public class MySqlOrderRepository implements OrderRepository {│
│      // MySQL实现...                                       │
│  }                                                       │
│                                                          │
│  @Repository                                             │
│  public class MongoOrderRepository implements OrderRepository {│
│      // MongoDB实现...                                     │
│  }                                                       │
│                                                          │
│  // 测试:使用内存实现                                       │
│  public class InMemoryOrderRepository implements OrderRepository {│
│      private Map<OrderId, Order> store = new HashMap<>();│
│      // 内存实现,毫秒级测试                                 │
│  }                                                       │
│                                                          │
└─────────────────────────────────────────────────────────┘

6.2 依赖注入实现DIP

java 复制代码
/**
 * Spring的依赖注入:DIP的工业级实现
 */

// 领域层(高层):定义接口
package com.example.order.domain;

public interface PaymentGateway {
    PaymentResult charge(Money amount, CardInfo card);
    PaymentResult refund(String transactionId, Money amount);
}

// 应用层(高层):使用接口
package com.example.order.application;

@Service
public class PaymentService {
    
    private final PaymentGateway paymentGateway;  // 依赖抽象
    
    // 构造器注入(DIP + IoC)
    public PaymentService(PaymentGateway paymentGateway) {
        this.paymentGateway = paymentGateway;
    }
    
    public void processPayment(Order order, CardInfo card) {
        PaymentResult result = paymentGateway.charge(order.getTotal(), card);
        // ...
    }
}

// 基础设施层(低层):实现接口
package com.example.order.infrastructure;

@Component
public class StripePaymentGateway implements PaymentGateway {
    
    private final StripeClient stripeClient;
    
    @Override
    public PaymentResult charge(Money amount, CardInfo card) {
        // Stripe API调用
        Charge charge = stripeClient.charges().create(params);
        return mapToResult(charge);
    }
    
    // ...
}

// 测试层:Mock实现
@TestConfiguration
public class TestConfig {
    
    @Bean
    @Primary
    public PaymentGateway mockPaymentGateway() {
        return Mockito.mock(PaymentGateway.class);
    }
}

七、SOLID原则协同工作

复制代码
┌─────────────────────────────────────────────────────────┐
│  SOLID原则之间的关系                                        │
├─────────────────────────────────────────────────────────┤
│                                                          │
│  ┌─────────────────────────────────────────────────┐    │
│  │              DIP(依赖倒置)                      │    │
│  │         基础设施:依赖抽象的机制                    │    │
│  └─────────────────────────────────────────────────┘    │
│                          │                               │
│                          ▼                               │
│  ┌─────────────────────────────────────────────────┐    │
│  │              ISP(接口隔离)                      │    │
│  │         抽象设计:小而专的接口                     │    │
│  └─────────────────────────────────────────────────┘    │
│                          │                               │
│                          ▼                               │
│  ┌─────────────────────────────────────────────────┐    │
│  │              LSP(里氏替换)                      │    │
│  │         实现约束:子类可替换父类                   │    │
│  └─────────────────────────────────────────────────┘    │
│                          │                               │
│                          ▼                               │
│  ┌─────────────────────────────────────────────────┐    │
│  │              OCP(开闭原则)                      │    │
│  │         扩展机制:新增代码而非修改                  │    │
│  └─────────────────────────────────────────────────┘    │
│                          │                               │
│                          ▼                               │
│  ┌─────────────────────────────────────────────────┐    │
│  │              SRP(单一职责)                      │    │
│  │         基础:每个类只有一个变化原因                │    │
│  └─────────────────────────────────────────────────┘    │
│                                                          │
│  协同示例:                                                │
│  • SRP拆分职责 → 识别变化方向                              │
│  • OCP定义扩展点 → 抽象接口                                │
│  • ISP细化接口 → 避免胖接口                                │
│  • LSP保证实现 → 子类可替换                                │
│  • DIP管理依赖 → 依赖抽象而非实现                          │
│                                                          │
└─────────────────────────────────────────────────────────┘

八、生产级实践检查清单

原则 检查项 工具支持
SRP 类行数 < 200,方法行数 < 30 Checkstyle, SonarQube
SRP 类变更原因单一(Git历史分析) Git log
OCP 新增功能通过新增类实现 ArchUnit测试
OCP if-else if链判断类型 PMD规则
LSP 子类无UnsupportedOperationException 代码审查
LSP 单元测试使用父类类型引用子类 测试用例设计
ISP 接口方法数 < 5 Checkstyle
ISP 客户端只依赖使用的方法 IDE依赖分析
DIP 包内无import具体实现类 ArchUnit
DIP 构造器参数为接口/抽象类 代码审查

九、总结

原则 核心思想 违反症状 解决方案
SRP 一个类一个职责 上帝类、频繁修改 拆分、提取
OCP 扩展开放,修改关闭 if-else链、修改现有代码 策略模式、抽象
LSP 子类可替换父类 类型检查、空实现 组合、契约设计
ISP 接口小而专 胖接口、空实现 接口拆分
DIP 依赖抽象 new具体类、无法测试 依赖注入、接口

SOLID不是教条,而是指导:

  • 初学者:严格遵循,培养设计直觉
  • 进阶者:理解权衡,灵活应用
  • 专家者:打破规则,创造更好的规则

参考文档

  • Agile Software Development, Principles, Patterns, and Practices - Robert C. Martin
  • Clean Architecture - Robert C. Martin
  • Design Patterns - GoF
相关推荐
那我掉的头发算什么1 小时前
【图书管理系统】基于Spring全家桶的图书管理系统(上)
java·服务器·数据库·spring boot·后端·spring·mybatis
cjl_8520082 小时前
MS SQL Server 实战 排查多列之间的值是否重复
java
海兰2 小时前
ES 9.3.0 日志模式分析
java·大数据·elasticsearch
程序员敲代码吗2 小时前
微服务熔断降级配置详解与实践:使用Sentinel和Nacos
java·微服务·sentinel
予枫的编程笔记2 小时前
【YF技术周报 Vol.01】OpenAI 国会指控 DeepSeek,字节发布 Seedance 2.0,Java 26 预览版来了
java·人工智能·openai·后端开发·ai技术·spring ai·deepseek
java1234_小锋2 小时前
Java高频面试题:Zookeeper节点宕机如何处理?
java·zookeeper·java-zookeeper
欧恩意10 小时前
【Tools】Java反汇编工具推荐
java·汇编
寻星探路11 小时前
【JVM 终极通关指南】万字长文从底层到实战全维度深度拆解 Java 虚拟机
java·开发语言·jvm·人工智能·python·算法·ai
lbb 小魔仙11 小时前
【Java】Java 实战项目:手把手教你写一个电商订单系统
android·java·python