知识库

先学知识点,再做题检验。当前:面向对象技术

01. 计算机系统知识 (13个) 02. 程序语言基础 (3个) 03. 操作系统 (8个) 04. 软件工程 (8个) 05. 数据结构与算法 (23个) 06. 数据库系统 (11个) 07. 计算机网络 (12个) 08. 面向对象技术 (10个) 09. 信息安全 (4个) 10. 知识产权与标准化 (4个) 11. 多媒体基础 (2个) 12. 项目管理 (4个)
OO基本概念
面向对象三大特性 重点 难度 2/3
通俗理解
面向对象三大特性就像现实世界的组织方式:封装就是把东西装进盒子里只留一个小口给别人用(自己内部怎么搞不用管);继承就是\"儿子长得像老子\",子类自动拥有父类的属性和方法,还可以添加自己的独特之处;多态就是\"同一个动作不同的表现\"——比如同样是\"叫\",狗汪汪叫、猫喵喵叫,同一个接口不同的实现。
核心公式/考点
• 封装(Encapsulation):
— 将数据和操作方法捆绑在一起,对外隐藏内部实现细节
— 通过访问控制符实现:private(类内访问)、protected(类内+子类)、public(所有)
— 优点:安全性、模块化、降低耦合
• 继承(Inheritance):
— 子类继承父类的属性和方法(非私有),可扩展或重写
— 单继承:一个子类只有一个直接父类(Java、C#)
— 多继承:一个子类可继承多个父类(C++),会引发菱形继承问题
— 继承关系是\"is-a\"关系(如Dog is-a Animal)
• 多态(Polymorphism):
— 同一操作作用于不同对象产生不同的执行结果
— 编译时多态(重载Overload):同名方法不同参数,编译时决定
— 运行时多态(重写Override):父类引用指向子类对象,运行时决定
— 实现条件:继承 + 方法重写 + 父类引用指向子类对象
表格对比
特性核心思想实现方式好处
封装信息隐藏访问控制符+getter/setter安全性、低耦合
继承复用+扩展extends关键字代码复用、层次化
多态一个接口多种实现重写+动态绑定灵活、可扩展
真题演练
例题:下列关于面向对象中多态的叙述,正确的是?
A) 多态是指不同的对象可以有相同的名字
B) 多态是指在运行时通过动态绑定实现不同行为
C) 多态只能通过继承实现
D) 多态是指类的属性可以取不同的值
解:多态是指同一操作作用于不同对象产生不同的执行结果,通过方法重写和动态绑定在运行时实现。A是重载,C不够准确(也可通过接口实现),D是属性赋值。答案:B。
注意事项
• 封装不是\"不让人用\"而是\"提供安全便捷的接口\"(对外公开方法,隐藏私有字段)
• 继承破坏了封装性(子类依赖父类实现),所以优先考虑组合而不是继承(组合优于继承原则)
• 多态的必要条件:继承/实现 + 方法重写 + 父类引用指向子类对象(向上转型)
• 重载(Overload)是编译时多态(静态绑定),重写(Override)是运行时多态(动态绑定)
• 真题常考:判断代码体现了哪种特性、重载和重写的区别
类间六大关系 重点 难度 2/3
通俗理解
类和类之间有六种关系,从弱到强:依赖(临时用一下)、关联(长期认识)、聚合(整体包含部分但部分可独立)、组合(整体与部分同生共死)、继承(父子关系)、实现(接口约定)。就像人与人之间的关系:依赖是\"我打车去机场\"(用完就结束),关联是\"我有朋友\"(长期认识),聚合是\"班级里有学生\"(学生换了班级还是学生),组合是\"人有心脏\"(人没了心脏也没了)。
核心公式/考点
• 六大关系(从弱到强):
1.依赖(Dependency):一个类使用另一个类(局部变量、方法参数、静态方法调用)
— UML:虚线箭头+箭头指向被依赖方
2.关联(Association):一个类知道另一个类的存在(成员变量)
— UML:实线箭头(单向)或实线(双向)
— 可标注多重性:1, 0..1, 0..*, 1..*
3.聚合(Aggregation):整体-部分关系,部分可脱离整体独立存在(空心菱形在整体侧)
— UML:空心菱形+实线
4.组合(Composition):整体-部分关系,部分与整体同生命周期(实心菱形在整体侧)
— UML:实心菱形+实线
5.继承/泛化(Generalization):子类继承父类(is-a关系)
— UML:空心三角形+实线(子类指向父类)
6.实现(Realization):类实现接口
— UML:空心三角形+虚线(实现类指向接口)
表格对比
关系强度表示UML符号代码体现
依赖最弱uses-a虚线箭头方法参数、局部变量
关联has-a实线箭头成员变量
聚合owns-a空心菱形成员变量(整体不负责创建和销毁)
组合contains-a实心菱形成员变量(整体负责创建和销毁)
继承次强is-a空心三角形+实线extends
实现较强契约空心三角形+虚线implements
真题演练
例题:在UML类图中,表示组合关系的符号是?
A) 空心菱形+实线 B) 实心菱形+实线 C) 空心三角形+实线 D) 虚线箭头
解:空心菱形+实线表示聚合(Aggregation),实心菱形+实线表示组合(Composition),空心三角形+实线表示继承(Generalization),虚线箭头表示依赖(Dependency)。答案:B。
注意事项
• 聚合和组合的核心区别:生命周期是否一致(组合中部分随整体创建/销毁)
• 区分关联和依赖:关联是\"长期\"成员变量关系,依赖是\"临时\"方法参数/局部变量关系
• 多重性标注(Multiplicity)常见于关联关系:1(恰好一个)、0..1(0或1个)、0..*(0或多个)、1..*(1或多个)
• 真题常考:给一段代码判断类间关系类型、UML图示中各种关系的符号
• 注意有些教材把\"依赖\"视为最弱关系,\"实现\"视为继承的变体,排序可能不同
✏️ 做这节的题(11题)
UML图
UML用例图 重点 难度 2/3
通俗理解
用例图是从用户视角看系统的功能需求——就像餐馆的菜单:顾客(参与者)可以看到哪些菜(用例),以及菜和菜之间的关系(比如点菜→结账的包含关系)。用例图不关心内部怎么实现,只关心\"用户能用系统做什么\"。
核心公式/考点
• 三大元素:
参与者(Actor):与系统交互的人或外部系统(用小人图标表示)
用例(Use Case):系统提供的功能(用椭圆表示)
系统边界(System Boundary):用矩形框表示系统的范围
• 关系类型:
关联(Association):参与者和用例之间(实线)
包含(Include):一个用例必然包含另一个用例的行为(虚线箭头+<<include>>)
如\"下单\"包含\"支付\"(每次下单都必须支付)
扩展(Extend):一个用例在特定条件下扩展另一个用例的行为(虚线箭头+<<extend>>)
如\"取款\"在余额不足时扩展\"显示错误\"(不是每次取款都触发)
泛化(Generalization):用例或参与者之间的父子关系(空心三角形+实线)
• 包含vs扩展:
include是\"一定会执行\"的必须步骤,extend是\"可能执行\"的可选步骤
表格对比
关系UML符号方向含义示例
关联实线参与者→用例参与者参与用例顾客→点餐
包含虚线+<<include>>基础→被包含必须调用下单→include→支付
扩展虚线+<<extend>>扩展→基础条件触发显示错误→extend→取款
泛化空心三角+实线子→父继承关系会员→顾客
真题演练
例题:ATM取款系统中,\"取款\"用例与\"验证密码\"用例之间的UML关系是什么?
A) 关联 B) 包含 C) 扩展 D) 泛化
解:取款必然需要先验证密码(每次取款都需验证),这是包含关系(<<include>>)。包含关系表示基础用例在执行过程中必须调用被包含用例。答案:B。
注意事项
• 包含(include)箭头方向:基础用例指向被包含用例(基础\"包含\"被包含)
• 扩展(extend)箭头方向:扩展用例指向基础用例(扩展\"扩展\"基础),不要搞反
• 参与者不一定是人,可以是外部系统(如银行支付系统、第三方OAuth)
• 用例图关注\"功能需求\",不关心顺序和内部实现细节
• 真题常考:判断用例间是include还是extend关系、识别参与者
UML类图 重点 难度 2/3
通俗理解
类图是UML中最核心的图,相当于建筑的\"结构蓝图\"——展示系统的静态结构:有哪些类、类的属性和方法、类之间的关系。一个类用长方形表示,分三格:上面类名、中间属性、下面方法。就像身份证:姓名(类名)+ 身高体重(属性)+ 能做什么(方法)。
核心公式/考点
• 类图三部分:
类名(Name):通常斜体表示抽象类,<<interface>>表示接口
属性(Attributes):格式 \"可见性 名称:类型 [=默认值]\"
方法(Operations):格式 \"可见性 名称(参数:类型):返回类型\"
• 可见性符号:
+ public(公有的)
private(私有的)
# protected(受保护的)
~ package/default(包级可见)
• 类间关系(六大关系见id=65):依赖、关联、聚合、组合、继承、实现
• 抽象类(Abstract Class)用斜体或<<abstract>>标注
• 接口(Interface)用<<interface>>标注
• 多重性(Multiplicity):如0..1、0..*、1..*、1
表格对比
符号含义示例
+name:Stringpublic的name属性,String类型
-age:intprivate的age属性
+getName():Stringpublic的getName方法,返回String
#setAge(a:int):voidprotected的setAge方法,接收int不返回
<<interface>>接口
<<abstract>>或斜体抽象类或抽象方法
真题演练
例题:在UML类图中,一个类的属性标记为\"-balance:double\",其中\"-\"表示什么?
A) public B) private C) protected D) 静态
解:UML类图中可见性符号:+表示public,-表示private,#表示protected,~表示package。所以\"-\"表示private(私有),该属性只能在本类内部访问。答案:B。
注意事项
• 抽象类名和方法名用斜体表示(画图时注意),普通类正体
• 接口与抽象类的区别:接口全部是抽象方法(无实现),抽象类可以有已实现方法
• 关联关系上的多重性标注很重要——如\"一个部门有多个员工\"标记为1对0..*
• 类图展示的是系统的\"静态\"结构,不描述行为的时间顺序(那是序列图的职责)
• 真题常考:给一段代码画出对应类图、解读类图中各种符号的含义
UML序列图 重点 难度 2/3
通俗理解
序列图是UML的\"动态\"图之一,展示对象之间按时间顺序的消息交互。就像电影剧本——谁先说话、谁后说话、说了什么内容、花了多长时间。序列图有两根轴:水平轴是参与交互的对象,垂直轴是从上到下的时间线。主要用来描述一个用例场景的具体执行流程。
核心公式/考点
• 基本元素:
生命线(Lifeline):垂直虚线,表示对象在时间上的存在
激活条(Activation Bar):竖直矩形条,表示对象正在执行操作的时间段
消息(Message):水平箭头,表示从一个对象到另一个对象的消息
• 消息类型:
同步消息(Synchronous):实心箭头+实线,发送方等待(调用方法)
异步消息(Asynchronous):空心箭头+实线,发送方不等待继续执行
返回消息(Return):虚线箭头,方法返回值
自调用消息(Self-Message):箭头指向自身生命线(调用自己的另一个方法)
• 交互片段(Combined Fragment):
alt:条件选择(if-else)
opt:可选片段(if)
loop:循环
par:并行(多线程)
break:跳出循环
表格对比
消息类型UML符号示例说明
同步消息实心箭头+实线调用方法发方等待直到方法返回
异步消息空心箭头+实线发送信号发方立即继续执行
返回消息虚线箭头return值方法的返回值
自调用回到自身本对象递归调用调用自身其他方法
真题演练
例题:在UML序列图中,表示对象在某个时间段处于活动状态的竖条叫做什么?
A) 生命线 B) 激活条 C) 消息 D) 交互片段
解:序列图中,生命线是对象存在的垂直虚线(A),激活条(激活棒/Execution Occurrence)是生命线上的竖直矩形条(B),表示对象正在执行操作的时间段。答案:B。
注意事项
• 序列图与通信图(协作图)可以互相转化,表达相同的信息(消息交互)
• 同步消息用实心箭头,异步消息用空心箭头——注意区分
• 生命线顶部是对象,格式为 \"对象名:类名\"(如 user:User),可省略一方
• 时间从上到下,越往下时间越晚
• 真题常考:根据场景描述画出序列图、解读序列图描述的对象交互顺序
✏️ 做这节的题(9题)
设计模式
创建型设计模式(5种) 重点 难度 2/3
通俗理解
创建型模式就像工厂生产产品——帮你\"如何创建对象\"的各种方式。不用你亲手new对象,让专门的对象帮你new。单例:公司只有一个CEO(全局唯一实例);工厂方法:不同的生产线造不同的车(每个产品对应一个工厂);抽象工厂:汽车集团旗下有多个品牌多个车型(产品族);建造者:点汉堡套餐可以自由选择配料(一步步构建复杂对象);原型:复印机复印文件(克隆已有对象)。
核心公式/考点
• 五种创建型模式:
1.单例模式(Singleton):确保一个类只有一个实例,提供全局访问点
— 懒汉式:使用时才创建(需考虑线程安全)
— 饿汉式:类加载时就创建(天生线程安全)
— 双重检测锁DCL(线程安全懒汉式)
2.工厂方法模式(Factory Method):定义一个创建对象的接口,让子类决定实例化哪个类
— 一个产品对应一个工厂(不违反OCP——新增产品就新增工厂类)
3.抽象工厂模式(Abstract Factory):创建一系列相关或相互依赖的对象(产品族)
— 比工厂方法级别更高:工厂方法只产一种产品,抽象工厂产一组产品
4.建造者模式(Builder):将一个复杂对象的构建与表示分离
— 适用于对象的属性很多、构造时需按特定步骤
— 经典例子:StringBuilder、Lombok的@Builder
5.原型模式(Prototype):通过克隆已有对象来创建新对象
— Java:clone() + Cloneable接口(浅克隆/深克隆)
— 适用于创建对象成本高(如数据库查询结果)
表格对比
模式核心思想适用场景关键类
Singleton唯一实例配置类、连接池、日志单例类
Factory Method延迟到子类决定创建哪个对象框架扩展、插件系统Creator + Product
Abstract Factory创建产品族UI主题切换、数据库驱动AbstractFactory + ConcreteFactory
Builder分步构建复杂对象对象参数多、有必选+可选参数Builder + Director
Prototype克隆已有对象对象创建成本高Prototype接口 + clone
真题演练
例题:JDBC中DriverManager.getConnection()返回数据库连接,这属于哪种设计模式?
A) 单例模式 B) 工厂方法模式 C) 抽象工厂模式 D) 建造者模式
解:DriverManager.getConnection()根据传入的URL自动选择合适的数据库驱动(如MySQL、Oracle)并创建连接。它定义了获取连接的接口,由不同驱动实现创建不同连接,属于工厂方法模式。答案:B。
注意事项
• 工厂方法vs抽象工厂:工厂方法产一种产品(一个产品等级结构),抽象工厂产多种产品(多个产品等级结构)
• 单例模式要特别注意线程安全和序列化破坏问题
• 建造者模式中Director不是必须的——客户端可以直接使用Builder
• 原型模式深克隆需要重写clone方法(浅克隆只复制引用,深克隆需复制引用指向的对象)
• 真题常考:给场景选择最适合的创建型模式、识别模式类型(通常考察区别)
结构型设计模式(7种) 重点 难度 2/3
通俗理解
结构型模式关注\"如何组合类和对象形成更大的结构\",就像搭积木。适配器:两孔插座插三孔插头需要转换头;桥接:画笔颜色和画笔类型可以自由组合(粗细×颜色=多种组合);组合:文件夹里有文件和子文件夹(树形结构整体/部分一致);装饰器:给咖啡加糖加奶(一层层包装扩展功能);外观:一键开机(封装复杂子系统提供简单接口);享元:书法家写同样的字可以用同一个模版(共享细粒度对象);代理:明星的经纪人帮你对接明星(控制访问)。
核心公式/考点
• 七种结构型模式:
1.适配器模式(Adapter):将一个类的接口转换成客户期望的另一个接口
— 类适配器(继承)、对象适配器(组合)
— 常用语:\"让不兼容的接口一起工作\"
2.桥接模式(Bridge):将抽象部分与实现部分分离,使它们可以独立变化
— 用组合替代继承,解决继承爆炸问题(2×2→2+2)
3.组合模式(Composite):将对象组合成树形结构表示\"部分-整体\"层次
— Leaf(叶子节点)和Composite(容器节点)都继承自同一抽象
4.装饰器模式(Decorator):动态给对象添加额外职责
— 比继承更灵活(不需要预定义所有组合)
— Java I/O流:new BufferedReader(new FileReader(\"file.txt\"))
5.外观模式(Facade):为子系统提供统一的高层接口
— 常用语:\"简化复杂系统的使用\"
6.享元模式(Flyweight):共享大量细粒度对象,减少内存占用
— 内部状态(共享)vs 外部状态(不共享,由客户端维护)
7.代理模式(Proxy):为其他对象提供一种代理以控制对这个对象的访问
— 远程代理、虚拟代理、保护代理、智能引用代理
表格对比
模式核心思想适用场景示例
Adapter接口转换新系统对接旧系统接口充电器转换头
Bridge抽象与实现分离多维度变化JDBC驱动
Composite树形结构中统一处理树形目录、菜单文件系统
Decorator动态添加职责功能层层叠加Java I/O流
Facade统一接口复杂子系统封装一键开机
Flyweight共享细粒度对象大量相似对象字符串常量池
Proxy控制访问延迟加载、权限控制AOP代理
真题演练
例题:Java I/O库中,new BufferedInputStream(new FileInputStream(\"file.txt\"))使用了哪种设计模式?
A) 适配器模式 B) 装饰器模式 C) 代理模式 D) 组合模式
解:BufferedInputStream层层包装FileInputStream,在原有功能上动态添加缓冲功能,且可以多层嵌套。这是装饰器模式的经典应用——一层层包装增强功能。答案:B。
注意事项
• 适配器(改变接口)和装饰器(增强功能)容易混淆:适配器是\"接口转换\",装饰器是\"功能增强\"
• 代理和装饰器结构相似,但目的不同:代理控制访问,装饰器增强功能
• 桥接模式与策略模式结构相似但关注点不同:桥接是结构型(分离抽象与实现),策略是行为型(封装算法)
• 组合模式的关键是透明性:客户端对Leaf和Composite操作一致
• 真题常考:给场景选择结构型模式、Java I/O中的模式识别
行为型设计模式(11种) 重点 难度 2/3
通俗理解
行为型模式关注\"对象之间的通信和职责分配\"——谁做什么、怎么协作。策略:去公司可以坐地铁/开车/骑车(不同的出行策略);模板方法:泡茶和泡咖啡都有着相同的步骤(烧水→冲泡→加料),只是具体实现不同;观察者:公众号更新后所有订阅用户收到通知(发布-订阅);责任链:报销单从组长→经理→总监逐级审批;迭代器:遍历集合的通用方式,不管底层是数组还是链表。
核心公式/考点
• 十一种行为型模式:
1.策略模式(Strategy):定义一系列算法,把它们封装起来,使其可以相互替换
— 避免大量if-else,符合开闭原则
2.模板方法模式(Template Method):定义算法的骨架,将一些步骤延迟到子类中实现
— 父类控制流程,子类实现细节(好莱坞原则:\"不要调用我,我会调用你\")
3.观察者模式(Observer):定义对象之间的一对多依赖,当一个对象改变时自动通知依赖对象
— 松耦合:主题不知道观察者的具体类
4.责任链模式(Chain of Responsibility):多个对象连成链,请求沿链传递直到被处理
— 适用于审批流程、日志过滤
5.命令模式(Command):将请求封装为对象,支持参数化、队列、日志、撤销
— 请求者和执行者解耦
6.迭代器模式(Iterator):顺序访问聚合对象的元素而不暴露内部表示
— Java的Iterator接口
7.中介者模式(Mediator):用一个中介对象封装一组对象的交互
— 同事间不直接通信,通过中介协调
8.状态模式(State):允许对象在内部状态改变时改变其行为(类状态机)
— 将每个状态封装成独立的类
9.解释器模式(Interpreter):定义语言的文法表示,解释器解释语言中的句子
— 正则表达式引擎、SQL解析
10.备忘录模式(Memento):在不破坏封装的前提下捕获并外部化对象的状态
— 撤销操作(Ctrl+Z)
11.访问者模式(Visitor):在不改变元素类的前提下定义作用于元素的新操作
— 编译器抽象语法树
表格对比
模式关键词适用场景优点
Strategy算法族互换多种支付方式消除if-else
Template Method固定流程+可变步骤框架控制流程代码复用
Observer发布-订阅事件通知系统松耦合
Chain of Resp.逐级处理审批流、日志灵活组合
Command请求封装操作队列、撤销解耦调用方和执行方
Iterator遍历访问集合遍历统一遍历接口
Mediator对象间中介GUI组件交互减少网状依赖
State状态即行为订单状态流转消除状态判断
Visitor在不改类的前提下增加操作数据结构稳定但操作多变增加操作方便
真题演练
例题:Spring框架中ApplicationEvent和ApplicationListener用于实现事件驱动,这属于哪种设计模式?
A) 策略模式 B) 观察者模式 C) 模板方法模式 D) 责任链模式
解:ApplicationListener监听ApplicationEvent,当事件发布时所有对该事件感兴趣的监听者都会收到通知并处理。这是一对多的依赖关系——事件源(主题)通知所有监听者(观察者),属于观察者模式。答案:B。
注意事项
• 策略模式和状态模式结构相似:策略是客户选择算法,状态是状态自动切换行为
• 观察者模式中需要注意内存泄漏(观察者注册后忘记注销)
• 责任链模式可以灵活组合或改变链的顺序
• 模板方法中的钩子方法(Hook):子类可选覆盖,不是必须实现
• 命令模式常与备忘录模式结合实现撤销功能
• 真题常考:给场景选择行为型模式、Spring框架中的模式应用(IoC/DI、AOP、事件等)
✏️ 做这节的题(12题)
UML补充图
UML状态图与活动图 重点 难度 2/3
通俗理解
状态图关注一个对象的\"状态变化\"——像游戏角色的生命状态:满血→受伤→残血→死亡,遇到什么事件(被攻击)会切换状态。活动图关注\"业务流程\"——像做饭流程:洗菜→切菜→炒菜→装盘,有点像流程图,但支持并行分支(同时烧水和切菜)。
核心公式/考点
• 状态图(State Machine Diagram):
— 基本元素:初始状态(实心圆)、状态(圆角矩形)、转移(箭头)、事件(触发转移)、动作(转移时的行为)、结束状态(实心圆外环)
— 状态:对象在某个时刻的稳定状态(如\"等待中\"、\"处理中\"、\"已完成\")
— 事件:导致状态转移的触发条件(如\"收到支付通知\"→从\"待支付\"变成\"已支付\")
— 动作:状态转移过程中执行的操作
— 自转移:事件触发但状态不变(如不断\"刷新\"页面)
• 活动图(Activity Diagram):
— 基本元素:初始节点(实心圆)、活动(圆角矩形)、分支(菱形判断)、分叉与汇合(同步条/粗横线)、结束节点(实心圆外环)
— 分支(Decision):表示条件判断(一个入口两个出口)
— 分叉(Fork):表示并发开始(进入同步条后产生多个并发流)
— 汇合(Join):表示并发结束(多个流汇合到同步条)
— 泳道(Swimlane):按职责将活动分组到不同角色列中
表格对比
特性状态图活动图
关注点对象的状态变化业务流程/工作流
核心元素状态、事件、转移活动、分支、并发
适用场景单个对象生命周期多个对象间的业务流程
并发表示不直接支持(复合状态)支持(分叉/汇合)
类似有限状态机传统流程图
真题演练
例题:UML活动图中,表示并发开始和并发结束的记号是什么?
A) 菱形 B) 实心圆 C) 粗横线(同步条) D) 圆角矩形
解:活动图中,粗横线(同步条/Synchronization Bar)用于表示并发控制。分叉(Fork)用一条入箭头多条出箭头的同步条表示并发开始,汇合(Join)用多条入箭头一条出箭头的同步条表示并发结束。答案:C。
注意事项
• 区分活动图和状态图:活动图是\"做了什么\"(流程),状态图是\"处于什么状态\"(状态机)
• 状态图中的状态是\"稳定状态\",瞬态(如正在转账)不是状态,而是动作
• 活动图的分支(菱形)和分叉(同步条)不要混淆——分支是二选一,分叉是并行都做
• 泳道(Swimlane)用垂直虚线划分角色,每个活动属于一个泳道
• 真题常考:给定状态/活动图判断事件触发后的下一个状态、区分状态图和活动图
✏️ 做这节的题(2题)
OO设计原则
面向对象SOLID原则 重点 难度 2/3
通俗理解
SOLID是面向对象设计的五大原则缩写,相当于程序员写代码的\"交通规则\"——告诉你怎么设计类才不容易\"翻车\"。单责原则:一个类只干一件事(就像厨师只负责做菜,不负责收银);开闭原则:对扩展开放、对修改封闭(加新功能不修改旧代码);里氏替换:子类可以替换父类使用不产生问题(正方形不是长方形的问题);接口隔离:不要强迫客户端依赖它不需要的接口(瘦接口比胖接口好);依赖倒置:要依赖抽象不依赖具体实现(高层不依赖低层,都依赖接口)。
核心公式/考点
• S - 单一职责原则(Single Responsibility Principle):
一个类只应有一个引起它变化的原因(一个类只负责一件事)
目的:高内聚、低耦合
• O - 开闭原则(Open-Closed Principle):
对扩展开放(允许通过扩展增加新功能),对修改关闭(不修改已有代码)
实现方式:抽象化(接口/抽象类)+ 多态
• L - 里氏替换原则(Liskov Substitution Principle):
子类可以替换父类出现的地方,且程序行为不变
经典反例:正方形继承自长方形(修改宽会影响高,违反预期)
• I - 接口隔离原则(Interface Segregation Principle):
客户端不应该被强迫依赖于它不使用的接口
大接口应拆分为多个小接口(胖接口→瘦接口)
• D - 依赖倒置原则(Dependency Inversion Principle):
高层模块不应依赖低层模块,两者都应依赖抽象
抽象不应依赖细节,细节应依赖抽象
表格对比
原则一句话违反的例子解决方式
SRP一个类只做一件事一个类处理数据库+发邮件+写日志拆分多个类
OCP扩展开放修改封闭加新功能要改旧类(if-else满天飞)用接口+策略模式
LSP子类可替换父类正方形继承长方形改为抽象形状类
ISP接口要小而专一个大接口包含不相关的方法拆成多个小接口
DIP面向接口编程new具体类而不是依赖接口依赖注入+工厂
真题演练
例题:下列哪个设计原则提倡\"一个类只应有一个引起它变化的原因\"?
A) 开闭原则 B) 里氏替换原则 C) 单一职责原则 D) 接口隔离原则
解:单一职责原则(SRP)规定一个类只负责一个功能领域中的相应职责,引起类变化的原因只有一个。答案:C。
注意事项
• SOLID五个原则不是孤立的,相互支持(OCP通常需要LSP和DIP配合)
• 不要过度设计——SRP拆分太细会导致类爆炸,DIP太激进增加复杂度
• 里氏替换原则的关键:子类不能改变父类的前提条件和后置条件
• 依赖注入(DI)是DIP的常见实现方式(通过构造函数、Setter、接口注入)
• 真题常考:判断代码违反了哪个原则、给出场景选择应遵循的原则
✏️ 做这节的题(2题)