You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SOLID五大设计原则之间有什么关联?是否存在冗余可精简?

SOLID原则独立性相关问题解答

首先给出明确结论:SOLID五项原则是完全相互独立的,对任意一项原则,都可以写出满足其余四项、仅违反该原则的代码,该结论在所有组合下都成立。

以下针对每种违反场景,以C#代码为例做具体说明:

1. 违反单一职责原则(SRP),满足其余四项

SRP的核心是一个类只能有一个引发变更的原因。
示例:定义UserService类,内部同时实现用户密码规则校验、用户数据持久化两套逻辑。

  • 满足其余四项的原因:
    • OCP:新增用户相关的其他能力(比如用户消息推送)不需要修改现有UserService代码,可通过新增类实现
    • LSP:若该类继承自IUserService接口,所有子类都可以无缝替换父类使用,不会破坏继承逻辑
    • ISP:类仅依赖最小粒度的抽象接口IPasswordValidator、IUserDb,未被强制要求依赖不需要的方法
    • DIP:所有依赖都是抽象接口,没有直接依赖具体的密码校验实现、数据库实现
  • 违反SRP的原因:密码校验规则调整、用户持久化逻辑调整都会引发该类的修改,存在两个独立的变更原因。

2. 违反开闭原则(OCP),满足其余四项

OCP的核心是对扩展开放,对修改关闭。
示例:定义PaymentProcessor类,内部硬编码仅支持微信支付、支付宝两种支付渠道,新增银联支付必须修改该类的内部分支判断逻辑。

  • 满足其余四项的原因:
    • SRP:该类仅负责支付流程调度,没有其他无关职责
    • LSP:若该类继承自IPaymentProcessor接口,子类可以完全替换父类使用
    • ISP:类仅依赖支付相关的最小接口,没有多余依赖
    • DIP:依赖的是IPaymentChannel抽象,没有直接依赖微信、支付宝的具体实现
  • 违反OCP的原因:新增支付渠道必须修改现有类的代码,无法通过扩展的方式实现能力新增。

3. 违反里氏替换原则(LSP),满足其余四项

LSP的核心是子类必须可以完全替换父类使用,不会破坏原有程序逻辑。
示例:定义父类Rectangle(矩形),包含SetWidth()、SetHeight()、GetArea()三个方法;定义子类Square(正方形)继承Rectangle,重写SetWidth()和SetHeight()方法,调用任意一个时会同时修改宽和高保证二者相等。

  • 满足其余四项的原因:
    • SRP:两个类都仅负责自身的属性计算逻辑,没有多余职责
    • OCP:新增其他图形类型不需要修改现有矩形、正方形的代码
    • ISP:类仅依赖IShape等最小粒度接口,没有多余依赖
    • DIP:所有依赖都是抽象,没有依赖具体实现
  • 违反LSP的原因:若存在函数接收Rectangle类型参数,先调用SetWidth(2)、SetHeight(3)再获取面积,预期返回值为6,传入Square实例时返回值为9,原有逻辑被破坏,子类无法替换父类使用。

4. 违反接口隔离原则(ISP),满足其余四项

ISP的核心是不要强迫类实现它不需要的接口方法。
示例:定义大接口IWorker,包含Work()、Eat()两个方法;定义RobotWorker类实现IWorker接口,机器人不需要吃饭,因此Eat()方法内部直接抛出NotImplementedException。

  • 满足其余四项的原因:
    • SRP:RobotWorker仅负责机器人工作逻辑,没有多余职责
    • OCP:新增其他类型的工人不需要修改现有代码
    • LSP:RobotWorker实现了IWorker的所有方法,替换为父类接口使用时,只要不调用Eat()方法就不会出现逻辑问题,符合替换规则
    • DIP:所有依赖都是抽象,没有依赖具体实现
  • 违反ISP的原因:RobotWorker被迫实现了自身完全不需要的Eat()方法,依赖了不需要的接口能力。

5. 违反依赖倒置原则(DIP),满足其余四项

DIP的核心是高层模块依赖抽象,不依赖具体实现;抽象不依赖细节,细节依赖抽象。
示例:定义OrderService类,直接依赖具体实现类SqlOrderRepository做订单持久化,而不是依赖IOrderRepository抽象接口。

  • 满足其余四项的原因:
    • SRP:OrderService仅负责订单业务逻辑处理,没有多余职责
    • OCP:新增其他订单业务能力不需要修改现有代码
    • LSP:若OrderService有子类,完全可以替换父类使用
    • ISP:没有依赖任何不需要的接口方法
  • 违反DIP的原因:需要将订单存储从SQL数据库切换为MongoDB时,必须修改OrderService的内部代码,高层模块直接依赖了底层实现细节。

关于你提到的原则边界重叠、是否可以精简的问题:五项原则是从不同维度对代码设计做约束,实际开发中设计良好的代码往往会同时符合多个原则,因此会产生边界重叠的错觉。比如符合LSP的代码通常也更容易满足OCP,但二者的约束方向完全不同:LSP规范的是继承关系的正确性,OCP规范的是扩展的灵活性,不存在谁覆盖谁的情况。行业内确实存在一些对SOLID做精简的工程实践讨论,但大多是针对中小型项目的取舍,而非原则层面的替换。大型长期维护的项目遵守全部五项原则,仍然是降低后续维护成本的最优选择。

内容的提问来源于stack exchange,提问作者Gregory Fenn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 02:27:02