设计模式考试复习知识点

设计模式的分类:

创建型(创建对象):工厂模式,抽象工厂模式,单例模式,建造者模式,原型

结构型(处理类和对象的组合):适配器模式,桥接模式,组合模式,装饰模式,外观模式,享元模式,代理模式

行为型(描述类或对象怎样交互和怎样分配职责):职责链模式,命令模式,解释器模式,观察者模式,状态模式,策略模式,模板方法模式,访问者模式,迭代器模式,备忘录模式,中介者模式

  1. 创建型模式(5 种):单例模式、原型模式、工厂方法模式、抽象工厂模式、建造者模式。记忆口诀:“单原工抽建,对象创建有方案”。单例模式确保全局只有一个实例;原型模式通过克隆创建对象;工厂方法模式由子类决定创建对象的具体类型;抽象工厂模式创建一系列相关对象;建造者模式将对象的构建和表示分离。

  1. 结构型模式(7 种):代理模式、适配器模式、桥接模式、装饰器模式、外观模式、享元模式、组合模式。记忆口诀:“代适桥装外享组,结构优化有高招”。代理模式为其他对象提供代理以控制访问;适配器模式转换接口适配;桥接模式分离抽象和实现;装饰器模式动态添加功能;外观模式提供统一接口;享元模式共享对象减少内存;组合模式将对象组合成树形结构。

  1. 行为型模式(12 种):策略模式、模板方法模式、观察者模式、迭代器模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式、调停者模式。记忆口诀:“策模观迭责命备,状访中解调行为”。策略模式定义算法族;模板方法模式定义算法骨架;观察者模式实现对象间依赖;迭代器模式遍历集合;责任链模式处理请求链;命令模式封装请求;备忘录模式保存和恢复状态;状态模式根据状态改变行为;访问者模式分离数据结构和操作;中介者模式减少对象间耦合;解释器模式解释语言;调停者模式协调对象交互。

24 种设计模式具体案例分享

通过具体案例能够更直观地记忆 24 种设计模式,下面从创建型、结构型、行为型三类模式入手,结合生活与软件开发场景,带你深入了解这些设计模式的实际应用。

一、创建型模式案例

\1. 单例模式

在 Java 的日志记录中,java.util.logging.Logger 类通常采用单例模式实现。整个应用程序中无论在多少个类中获取日志记录器实例,始终都是同一个实例。这样能确保日志的统一管理和输出,避免多实例导致的日志混乱和资源浪费。

\2. 原型模式

在游戏开发中,游戏角色的创建常常使用原型模式。例如,游戏中有多个同类型的士兵角色,每个士兵角色的基本属性(如生命值、攻击力、防御值等)相同,但可能有不同的位置和状态。开发者可以先创建一个士兵原型对象,然后通过克隆这个原型对象,快速生成多个士兵角色,极大提高开发效率。

\3. 工厂方法模式

以电商系统为例,系统中需要创建不同类型的商品对象,如电子产品、服装、食品等。可以定义一个抽象的商品工厂类,包含抽象的创建商品方法。然后针对每种商品类型创建具体的工厂子类,如电子产品工厂类创建电子产品对象,服装工厂类创建服装对象。通过这种方式,当需要添加新的商品类型时,只需要新增对应的工厂子类即可,符合开闭原则。

\4. 抽象工厂模式

在汽车制造模拟系统中,汽车由多个部件组成,如发动机、轮胎、车身等。可以使用抽象工厂模式,定义一个抽象的汽车工厂接口,该接口包含创建发动机、轮胎、车身等部件的抽象方法。然后有不同品牌汽车的具体工厂类,如宝马工厂类、奔驰工厂类,每个具体工厂类实现接口方法,创建对应品牌汽车的各个部件。这样可以方便地创建不同品牌的汽车,同时保证部件的一致性和协调性。

\5. 建造者模式

以建造房屋为例,房屋建造过程复杂,包括打地基、砌墙、安装门窗、装修等步骤。可以使用建造者模式,定义一个抽象的房屋建造者类,包含建造各个部分的抽象方法。然后有具体的房屋建造者子类,如别墅建造者、普通住宅建造者,它们实现抽象方法完成具体房屋的建造过程。最后通过一个指挥者类来安排建造顺序,调用建造者的方法完成房屋建造。

二、结构型模式案例

\1. 代理模式

在网络访问中,VPN(虚拟专用网络)就是代理模式的典型应用。当用户访问某些受限的国外网站时,用户的网络请求会先发送到 VPN 服务器(代理服务器),VPN 服务器代替用户去访问目标网站,获取数据后再返回给用户。这样不仅突破了网络限制,还能隐藏用户真实的 IP 地址,保护用户隐私。

\2. 适配器模式

在计算机硬件领域,USB 接口和 Type-C 接口的转换头就是适配器模式的体现。当电脑只有 Type-C 接口,而用户的设备是 USB 接口时,通过 USB-Type-C 转换头这个适配器,就能将 USB 设备连接到电脑上,实现数据传输和充电功能,解决了接口不兼容的问题。

\3. 桥接模式

在手机操作系统开发中,手机的操作系统(如安卓、iOS)和手机硬件(如屏幕、摄像头、处理器等)之间可以使用桥接模式。将操作系统和硬件抽象成两个独立的维度,操作系统可以调用硬件的接口来实现各种功能,并且操作系统和硬件可以独立进行升级和扩展。比如,安卓系统可以适配不同厂商生产的屏幕,新的屏幕硬件也能快速适配到安卓系统中。

\4. 装饰器模式

在文本编辑软件中,对文字的格式设置可以使用装饰器模式。假设文本编辑软件有一个基础的文本显示类,当用户想要给文字添加加粗、斜体、下划线等效果时,可以使用对应的装饰器类,如加粗装饰器类、斜体装饰器类等,动态地给基础文本显示对象添加格式功能,而且可以同时添加多个装饰器,实现多种格式组合。

\5. 外观模式

在家庭影院系统中,外观模式得到了很好的应用。家庭影院系统包含投影仪、音响、蓝光播放器、幕布等多个设备,操作复杂。可以设计一个统一的家庭影院外观类,提供简单的操作方法,如 “打开影院”“关闭影院” 等。当调用 “打开影院” 方法时,外观类会依次控制投影仪开机、音响启动、蓝光播放器打开、幕布降下等一系列操作,简化了用户的使用流程。

\6. 享元模式

在围棋游戏中,棋盘上的棋子可以使用享元模式。棋盘上会有大量的黑子和白子,它们的外观和属性基本相同,只是位置不同。可以创建少量的黑子和白子对象作为享元对象,当需要在棋盘上显示棋子时,通过设置棋子的位置来复用这些享元对象,减少内存占用,提高游戏运行效率。

\7. 组合模式

在文件系统中,文件夹和文件的管理采用了组合模式。文件夹可以包含文件和子文件夹,子文件夹又可以包含文件和孙文件夹,形成树形结构。可以将文件夹和文件抽象为一个统一的组件接口,定义通用的操作方法,如获取名称、获取大小等。文件夹类实现该接口,并可以包含多个组件对象(文件或子文件夹),实现对文件和子文件夹的管理和操作。

三、行为型模式案例

\1. 策略模式

在电商系统的促销活动中,不同的促销策略可以使用策略模式。比如有满减策略(满 200 减 50)、打折策略(全场 8 折)、赠品策略(买一送一)等。定义一个抽象的促销策略接口,包含计算优惠后价格的抽象方法。然后每个具体的促销策略类实现该接口,在订单结算时,根据不同的促销活动选择对应的策略对象来计算最终价格。

\2. 模板方法模式

在考试系统中,不同科目的考试流程类似,都包含开始考试、答题、提交试卷等步骤,但具体题目和答题方式不同。可以定义一个抽象的考试模板类,包含考试流程的模板方法,如 “开始考试”“答题”“提交试卷” 等,其中 “答题” 方法定义为抽象方法。然后针对不同科目创建具体的考试子类,如数学考试类、语文考试类,实现抽象的 “答题” 方法,完成具体科目的考试流程。

\3. 观察者模式

在股票交易软件中,股票价格的实时变化通知采用观察者模式。投资者(观察者)关注某只股票(被观察者)后,当股票价格发生变化时,股票对象会通知所有关注它的投资者,投资者收到通知后更新自己界面上的股票价格信息。

\4. 迭代器模式

在 Java 集合框架中,ArrayList、HashMap 等集合类都实现了迭代器模式。以 ArrayList 为例,通过调用 iterator() 方法可以获取一个迭代器对象,使用迭代器对象的 hasNext() 和 next() 方法可以遍历 ArrayList 中的元素,隐藏了集合内部的遍历实现细节,使遍历操作更加统一和方便。

\5. 责任链模式

在公司的请假审批流程中,责任链模式得到广泛应用。员工请假需要经过不同层级的领导审批,如部门主管、经理、总经理等。可以将每个审批者定义为一个处理者对象,形成一个责任链。当员工提交请假申请时,请求从部门主管开始处理,如果主管有权限审批则处理,否则将请求传递给下一个处理者(经理),依次类推,直到请求被处理。

\6. 命令模式

在游戏中的撤销操作可以使用命令模式。玩家在游戏中的每一个操作(如移动角色、攻击敌人、使用道具等)都可以封装成一个命令对象,命令对象包含执行操作和撤销操作的方法。将这些命令对象存储在命令队列中,当玩家想要撤销某个操作时,从命令队列中取出对应的命令对象,调用其撤销方法即可。

\7. 备忘录模式

在文本编辑器的撤销功能中,备忘录模式发挥重要作用。在用户编辑文本的过程中,每一次编辑操作前,文本编辑器会创建一个备忘录对象,记录当前文本的状态。当用户点击撤销按钮时,编辑器可以从备忘录中恢复到之前的文本状态,实现撤销功能。

\8. 状态模式

在自动售货机系统中,状态模式用于管理售货机的不同状态。售货机有空闲、投币、出货、找零等状态,不同状态下对用户操作(如投币、选择商品)的响应不同。可以将每个状态定义为一个状态类,实现状态相关的操作方法,如投币方法、选择商品方法等。售货机根据当前状态调用相应状态类的方法,实现状态的转换和操作响应。

\9. 访问者模式

在电商商品统计系统中,有不同类型的商品(如电子产品、服装、食品),需要对商品进行不同的统计操作,如统计商品总价值、统计商品数量等。可以使用访问者模式,定义一个抽象的访问者接口,包含不同的统计方法,如 “统计总价值”“统计数量” 等。然后每个具体的商品类(如电子产品类、服装类)接受访问者对象,访问者对象在访问商品时执行相应的统计操作。

\10. 中介者模式

在聊天软件中,多个用户之间的消息交互可以使用中介者模式。用户之间不直接进行消息传递,而是通过聊天服务器(中介者)进行中转。用户发送消息给服务器,服务器再将消息转发给对应的接收用户,减少了用户之间的直接耦合,便于消息管理和功能扩展。

\11. 解释器模式

在正则表达式引擎中,解释器模式用于解释和执行正则表达式。正则表达式是一种用于匹配和处理文本的字符串模式,正则表达式引擎将正则表达式字符串解析成抽象语法树,然后通过解释器对抽象语法树进行解释和执行,判断输入的文本是否符合正则表达式的规则。

\12. 调停者模式

在机场调度系统中,飞机、塔台、登机口、行李处理系统等多个对象之间的交互可以使用调停者模式。这些对象之间的交互复杂,通过引入一个机场调度调停者对象,协调各个对象之间的操作。例如,当飞机降落时,调停者通知塔台安排降落跑道,通知登机口准备迎接飞机,通知行李处理系统准备接收行李,确保整个机场运营的有序进行。

通过这些丰富的案例,相信你能更轻松地记忆和理解 24 种设计模式,在实际开发中也能更好地运用它们解决问题。

以上案例涵盖多场景多领域,希望能助力你记忆设计模式。若你觉得某些案例不合适,或想补充特定场景案例,欢迎告诉我。

一、记忆口诀:

单开里迪接依迪(谐音:单开里递接力笛)

  • :单一职责原则(SRP)

  • :开闭原则(OCP)

  • :里氏替换原则(LSP)

  • :迪米特法则(LoD)

  • :接口隔离原则(ISP)

  • :依赖倒置原则(DIP)

  • :(重复)这里实际对应 合成复用原则(CRP)(部分资料中 “7 原则” 包含此原则,需注意不同资料的差异)。

二、核心原则详解(含案例和记忆技巧)

1. 单一职责原则(SRP, Single Responsibility Principle)
  • 定义:一个类 / 模块只负责一项职责。

  • 案例:

    • 错误:手机类同时处理 “通信” 和 “拍照”,职责混合。

    • 正确:拆分为通信模块相机模块,各自独立。

  • 记忆点职责唯一,避免 “大杂烩” 类。

2. 开闭原则(OCP, Open/Closed Principle)
  • 定义:软件实体(类、模块等)应对扩展开放,对修改关闭

  • 案例:

    • 需求:增加 “圆形” 图形类,原有 “绘图程序” 无需修改代码,只需新增圆形类实现接口。

  • 记忆点扩展优先,修改次之,多用抽象和继承。

3. 里氏替换原则(LSP, Liskov Substitution Principle)
  • 定义:子类必须能替换其父类,且不破坏程序正确性。

  • 案例:

    • 错误:“正方形” 继承 “矩形”,但子类修改了 “宽高可独立变化” 的行为(违反父类约定)。

  • 记忆点子类是父类的 “特殊版本”,而非 “相反版本”

4. 迪米特法则(LoD, Law of Demeter)
  • 定义:一个对象应尽可能少地了解其他对象(降低耦合)。

  • 案例:

    • 错误:A 类直接调用 D 类的方法(A→B→C→D),违反 “最少知识”。

    • 正确:通过 B 类间接调用,或让 C 类处理与 D 的交互。

  • 记忆点只和 “直接朋友” 打交道(成员变量、方法参数等直接关联对象)。

5. 接口隔离原则(ISP, Interface Segregation Principle)
  • 定义:客户端不应该依赖它不需要的接口,应拆分为更小的专用接口。

  • 案例:

    • 错误:定义 “动物接口” 包含 “飞”“跑”“游泳”,导致企鹅类被迫实现 “飞”。

    • 正确:拆分为飞行动物接口陆行动物接口等,按需实现。

  • 记忆点接口要 “轻量”,避免 “胖接口”

6. 依赖倒置原则(DIP, Dependency Inversion Principle)
  • 定义:高层模块不依赖低层模块,两者都依赖抽象;抽象不依赖细节,细节依赖抽象。

  • 案例:

    • 错误:高层模块用户服务直接依赖低层模块MySQL数据库类

    • 正确:定义数据库接口,高层模块依赖接口,低层模块(MySQL/Redis)实现接口。

  • 记忆点面向接口编程,依赖抽象而非具体(“倒置” 指依赖关系从 “具体→具体” 变为 “抽象→具体”)。

7. 合成复用原则(CRP, Composite Reuse Principle)
  • 定义:优先使用组合 / 聚合(Has-A 关系)而非继承(Is-A 关系)来复用代码。

  • 案例:

    • 错误:“汽车类” 继承 “发动机类”(发动机是汽车的一部分,应为组合关系)。

    • 正确:汽车类包含发动机实例(car.engine = new Engine())。

  • 记忆点组合比继承更灵活,避免继承导致的 “紧耦合” 和 “脆弱性”。

三、对比记忆表

原则名称核心思想反例场景正向实践
单一职责职责分离类承担多个不相关功能拆分为独立模块
开闭原则扩展优先,修改关闭需求变更时直接修改旧代码通过抽象类 / 接口扩展新功能
里氏替换子类可安全替换父类子类重写父类核心方法导致错误子类遵循父类契约(方法参数、返回值)
迪米特法则降低对象间耦合跨多层调用对象内部方法通过中间层或参数传递交互
接口隔离接口细化,拒绝胖接口接口包含无关方法拆分为小接口,按需实现
依赖倒置依赖抽象而非具体高层模块直接依赖具体实现类定义接口,高层和低层依赖接口
合成复用组合优先于继承用继承实现 “部分 - 整体” 关系用成员变量持有其他对象实例

四、记忆技巧总结

  1. 口诀联想:用 “单开里迪接依迪” 谐音快速串联 7 个原则名称。

  2. 场景记忆:每个原则对应一个典型反例(如 “正方形继承矩形” 违反里氏替换),通过具体场景加深理解。

  3. 对比分组:

    • 设计目标:单一职责(职责清晰)、接口隔离(接口细化)。

    • 扩展能力:开闭原则(扩展优先)、依赖倒置(抽象解耦)。

    • 关系处理:里氏替换(继承正确性)、合成复用(组合 vs 继承)、迪米特法则(低耦合)。

1. 单一职责原则(SRP)

场景:医院的科室分工

  • 错误示例: 一个医生同时负责看病、开药、做手术、收费(职责混乱,效率低)。

  • 正确示例: 拆分为内科医生(诊断)、药剂师(配药)、外科医生(手术)、收费员(结算),各负其责。

  • 记忆点医院科室专业化分工,避免 “全能医生” 导致的混乱。

2. 开闭原则(OCP)

场景:手机系统的应用扩展

  • 错误示例: 手机系统预装应用固定,新增应用需修改系统底层代码。

  • 正确示例: 通过应用商店(扩展点)下载新应用,无需修改系统(如 iOS/Android)。

  • 记忆点手机应用商店,支持无限扩展但不修改系统核心。

3. 里氏替换原则(LSP)

场景:交通工具的速度限制

  • 错误示例自行车类继承机动车类,但自行车速度上限为 20km/h,重写父类的 “120km/h 限速” 方法,导致违反父类契约。

  • 正确示例自行车机动车继承自抽象交通工具类,各自实现合理的速度限制(自行车≤20km/h,汽车≤120km/h)。

  • 记忆点子类不能改变父类的核心行为(如限速),否则会导致 “父类被替换后程序异常”。

4. 迪米特法则(LoD)

场景:租房中介的角色

  • 错误示例: 租客直接联系房东,还要协调看房、签合同、维修等事宜(与多个对象交互,耦合高)。

  • 正确示例: 通过中介统一处理,租客只需对接中介,不直接与房东或维修工交互。

  • 记忆点租房通过中介,减少与 “陌生人” 的直接交互。

5. 接口隔离原则(ISP)

场景:健身教练的专业分工

  • 错误示例: 定义 “全能教练接口”,包含 “减脂”“增肌”“瑜伽”“拳击” 等所有方法,导致普通教练被迫实现不擅长的方法。

  • 正确示例: 拆分为减脂教练接口瑜伽教练接口等,教练按需实现(如瑜伽教练只实现瑜伽相关方法)。

  • 记忆点健身教练的专业认证,不强迫一个教练掌握所有技能。

6. 依赖倒置原则(DIP)

场景:智能家居系统

  • 错误示例智能灯光类直接依赖小米控制器,若更换为华为设备,需修改灯光类代码。

  • 正确示例: 定义控制器接口,灯光类依赖接口而非具体实现,可动态切换小米 / 华为控制器。

  • 记忆点智能家居的 “协议统一”,设备不依赖具体品牌,依赖标准接口。

7. 合成复用原则(CRP)

场景:汽车组装

  • 错误示例汽车类继承发动机类轮胎类(继承滥用,导致类爆炸)。

  • 正确示例: 汽车类通过组合持有发动机、轮胎的实例(car.engine = new V8Engine())。

  • 记忆点汽车组装厂,通过采购不同零件(组合)而非继承来生产汽车。

记忆强化技巧

  1. 制作原则卡片: 每张卡片写一个原则,正面画场景图(如迪米特法则画 “中介”),背面写定义和代码示例。

  2. 生活场景联想

    • 看到 “医院” 想单一职责

    • 用 “手机” 想开闭原则

    • 开车时想里氏替换(遵守交通规则 = 子类遵守父类契约)

  3. 代码对比记忆:

    原则错误代码示例正确代码示例
    单一职责class UserService处理登录 + 注册 + 支付拆分为LoginServiceRegisterService
    开闭原则修改旧代码添加新功能实现接口新增类,不修改原代码
    迪米特法则A.callB().callC().callD()A.callB(),B 内部处理 C 和 D 的调用

通过具体场景和生活化类比,设计原则会变得更加直观易懂,记忆也会更深刻!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

暴躁的秋秋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值