ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

【面向对象】面向对象设计原则:SOLID五大原则

2026/8/4 20:05:34 拓冰建站 浏览量
【面向对象】面向对象设计原则:SOLID五大原则 考点频率★★★★★上午选择题必考下午题设计类图时也常需体现这些原则难度⭐⭐⭐建议重点理解每个原则的核心含义和软考常考表述能根据场景判断是否违反了某条原则1️⃣ 为什么要学SOLID前面我们学了面向对象的三大特性封装、继承、多态但“会用”不等于“用好”。三个特性只能保证你写出面向对象的代码但写出来的代码是不是容易维护、容易扩展、容易测试——那是另外一回事。SOLID五大原则就是面向对象设计的“最佳实践清单”。它们告诉你怎么用封装、继承、多态才能写出“好”的代码。这五个原则合起来就是为了实现一个终极目标高内聚、低耦合。2️⃣ 单一职责原则SRPSingle Responsibility Principle定义一个类应该只有一个引起它变化的原因。换句话说一个类只负责一个功能领域的职责。核心思想一个类只做一件事。如果一件事做不好需要改不会连累其他不相干的功能。软考常考表述“将不同的职责分离到不同的类中”“一个类只承担一个职责”“变化点分散到不同的类中”反面示例违反SRPclass 员工 { 计算工资() // 财务部门关心 保存到数据库() // DBA关心 生成报表() // 管理层关心 }三个不同的职责混在一起改工资算法可能会影响数据库操作。正确做法拆成工资计算器、员工仓库、报表生成器三个独立的类。一句话一个类一个职责一个改动的理由。3️⃣ 开闭原则OCPOpen-Closed Principle定义软件实体类、模块、函数等应该对扩展开放对修改关闭。核心思想当需求变化时你应该通过新增代码来实现新功能而不是修改现有代码。软考常考表述“不修改原有代码通过扩展来实现新功能”“抽象化是开闭原则的关键”“面向接口编程”反面示例违反OCPclass 绘图 { 画(形状) { if (形状是圆形) { 画圆() } else if (形状是方形) { 画方() } // 新增三角形时要修改这个类 } }正确做法遵循OCPinterface 形状 { 画() } class 圆形 implements 形状 { 画() { 画圆 } } class 方形 implements 形状 { 画() { 画方 } } // 新增三角形只需新增类不修改已有代码一句话不改旧代码只加新代码。抽象是钥匙接口是锁芯。本质开闭原则是SOLID中最核心、最抽象的原则其他几个原则都是在不同层面上支撑“对扩展开放、对修改封闭”的手段。单一职责保证修改影响范围小里氏替换保证扩展不破坏继承体系接口隔离和依赖倒置保证扩展不引入不必要的依赖。4️⃣ 里氏替换原则LSPLiskov Substitution Principle定义子类型必须能够替换掉它们的父类型。凡是父类出现的地方子类都应该能够代替父类出现且程序行为不变。核心思想继承不能破坏父类的行为契约。子类可以扩展父类的功能但不能改变父类原有的行为含义。软考常考表述“子类可以替换父类”“子类不应重写父类中已定义的方法来改变其预期行为”“继承关系应该符合 is-a 关系”特别注意里氏替换原则是五个原则中最容易混淆的一个。它的关键不在于“子类能不能替换父类”语法上当然能而在于“替换后程序行为是否正确”。反面示例违反LSP——经典长方形/正方形问题class 长方形 { 设置宽度(w) { 宽度 w } 设置高度(h) { 高度 h } } class 正方形 extends 长方形 { 设置宽度(w) { 宽度 w; 高度 w } // 破坏了父类的契约 设置高度(h) { 高度 h; 宽度 h } // 父类说宽高独立子类说必须相等 }使用场景中如果某个函数要求宽高独立变化传入正方形就会出错。一句话子类可以替换父类且替换后程序照样跑。不改变父类行为的预期是底线。5️⃣ 接口隔离原则ISPInterface Segregation Principle定义客户端不应该被迫依赖它不使用的接口。应该将胖接口拆分成多个专一的小接口。核心思想一个类实现了某个接口就必须实现该接口的所有方法。如果接口里有这个类根本用不到的方法就说明接口设计得太“胖”了。软考常考表述“将大接口拆分为多个小接口”“不应该强迫用户依赖他们不需要的方法”“接口的粒度要小”反面示例违反ISPinterface 多功能设备 { 打印() 扫描() 传真() } class 普通打印机 implements 多功能设备 { 打印() { ... } 扫描() { 抛出异常 } // 普通打印机不支持扫描 传真() { 抛出异常 } // 普通打印机不支持传真 }正确做法拆分为可打印、可扫描、可传真三个独立接口。一句话胖接口拆成小接口别让实现类被迫实现它用不上的方法。6️⃣ 依赖倒置原则DIPDependency Inversion Principle定义高层模块不应该依赖低层模块二者都应该依赖其抽象抽象不应该依赖细节细节应该依赖抽象。核心思想要面向接口编程不要面向实现编程。依赖关系应该终止于抽象类或接口。软考常考表述“依赖抽象不依赖具体”“高层模块和低层模块都依赖接口”“抽象不依赖具体实现”反面示例违反DIPclass 支付服务 { 支付宝 支付工具; // 直接依赖具体类 支付() { 支付工具.扣款() } } // 如果要换成微信支付必须修改支付服务代码正确做法遵循DIPinterface 支付方式 { 扣款() } class 支付宝 implements 支付方式 { 扣款() { ... } } class 微信支付 implements 支付方式 { 扣款() { ... } } class 支付服务 { 支付方式 支付工具; // 依赖接口不依赖具体实现 支付() { 支付工具.扣款() } }一句话依赖接口不依赖具体类。细节依赖抽象抽象不依赖细节。7️⃣ SOLID五原则速查表原则缩写核心要点软考关键词单一职责SRP一个类只有一个职责一个职责、一个变化原因开闭原则OCP对扩展开放对修改关闭不修改原有代码、扩展里氏替换LSP子类可替换父类且行为不变子类替换父类、不改变预期行为接口隔离ISP胖接口拆成小接口不依赖不需要的方法、拆分接口依赖倒置DIP依赖抽象不依赖具体面向接口编程、依赖抽象8️⃣ 经典例题例题1某系统在增加新功能时只需要添加新的类而不需要修改现有类这体现了 原则。A. 单一职责B. 开闭原则C. 里氏替换D. 接口隔离解析“增加新功能而不修改现有类”是开闭原则的典型表述。选B。例题2某系统定义了一个“员工”类包含了计算工资、保存到数据库、生成报表三个方法。有开发人员建议将这个类拆分为三个独立的类。该建议主要依据 原则。A. 单一职责B. 开闭原则C. 接口隔离D. 依赖倒置解析将不同职责拆分到不同类中是单一职责原则的典型应用。选A。9️⃣ 记忆口诀单开里接依——SOLID要牢记。单一职责管好自己事开闭扩展不修旧。里氏子替父行为不走样。接口隔离拆胖接依赖倒置面向接口留。 小测验评论区对答案某系统中类A直接依赖于类B的具体实现。系统引入了一个新功能需要将类B替换为类C结果导致类A的代码也必须修改。这最可能违反了 原则。A. 单一职责B. 开闭原则C. 里氏替换D. 依赖倒置本专栏日更点击头像 → 专栏《软考中级高频考点》订阅第一时间接收新内容#软考中级 #软件设计师 #SOLID #单一职责 #开闭原则 #里氏替换 #接口隔离 #依赖倒置 #软考备考