SOLID五大原则是围绕“职责”和“依赖”的系统性思维工具:单一职责按变化原因拆分类;开闭与里氏替换用多态隔离变化并严守行为契约;接口隔离提供最小够用契约;依赖倒置要求高层模块依赖抽象且由使用者定义接口。

面向对象设计中的 SOLID 五大原则,不是代码规范清单,而是围绕“职责”和“依赖”展开的一套系统性思维工具。真正起作用的,是理解每条原则如何把变化关进独立的盒子,并让模块之间靠契约握手,而不是靠实现绑死。
单一职责:按变化原因拆分,不是按功能数量切分
一个类该不该拆,关键看它会不会因为不同原因被修改。比如用户登录逻辑调整、审计日志格式变更、数据库从 MySQL 换成 PostgreSQL——这三个变动彼此无关,就该对应三个类:Authenticator、AuditLogger、UserRepository。命名上避免 Utils、Helper 这类模糊词,用业务语义明确的名称,本身就是职责清晰的第一信号。
开闭+里氏替换:用多态隔离变化,同时守住行为边界
新增功能不改老代码,靠的是定义稳定接口(如 UserRepository),让新实现(PostgreSqlRepo、MockRepo)去实现它。但子类不能随意改变父类的行为契约:原方法接受非空字符串,子类不能突然要求必须带邮箱格式;原方法保证返回非 null 用户,子类也不能返回 null。违反这点,调用方就会在运行时崩溃。
接口隔离:给调用方最小够用的契约,不是堆满所有方法
别让一个 Service 类依赖包含 12 个方法的大接口。如果它只用其中 save() 和 findById(),那就定义一个精简接口(如 ReadonlyUserRepo 或 WritableUserRepo)。前端调用者、测试 Mock、缓存层各自按需选择,互不干扰。臃肿接口会迫使无关模块承担额外理解和维护成本。
依赖倒置:高层模块只认抽象,具体实现由外部注入
Service 类里写 new JdbcUserRepository() 是典型反模式。它直接绑死了技术细节,也堵死了替换路径。正确做法是声明依赖 UserRepository 接口,通过构造函数或配置把具体实现交出去。抽象接口应由使用方(如 Service)提出需求来定义,而不是由实现方(如数据库团队)拍板——谁消费,谁定契约。










