# 什么是设计模式?请简述其作用。

7 min read
Table of Contents

什么是设计模式?请简述其作用。

【核心定义】 设计模式是一套被反复使用、经过分类编目的、用于解决软件设计中特定问题的可复用解决方案,它代表了最佳实践,是面向对象软件设计的经验总结。

【关键要点】

  1. 本质是经验抽象:设计模式并非具体代码,而是对特定场景下通用设计问题的抽象描述,包括问题背景、解决方案及效果。
  2. 核心价值在于解耦与复用:通过提供标准化的设计结构,降低系统模块间的耦合度,提升代码的可维护性、可扩展性和可复用性。
  3. 分类明确:通常分为创建型(如工厂、单例)、结构型(如适配器、代理)和行为型(如观察者、策略)三大类,每类解决不同维度的设计问题。

【深度推导/细节】

  • 解决的核心矛盾:在软件复杂度增长与开发维护成本之间的矛盾。当需求频繁变更或系统规模扩大时,随意堆砌的代码会变得难以维护。设计模式通过预定义的角色与交互关系,强制约束了代码的组织方式,从而将变化隔离在局部。
  • 以“开闭原则”为例的逻辑拆解:
    • 问题:系统需要支持新功能,但修改原有代码可能引入风险。
    • 模式应用:采用策略模式。
    • 逻辑步骤:
      • Step 1: 定义一个策略接口,声明通用算法。
      • Step 2: 将系统中可变的算法部分抽离,实现为多个独立的策略类。
      • Step 3: 在上下文类中持有策略接口的引用,而非具体实现。
      • Step 4: 当需要新增算法时,只需实现新的策略类并注入上下文,无需修改任何原有策略类或上下文的代码。
    • 结果:系统对扩展开放,对修改关闭,完美体现了设计模式的核心价值。

【关联/对比】

  • 设计模式 vs. 框架/库:设计模式是概念性的指导方案,语言无关;框架(如Spring)是半成品的应用骨架,库(如Apache Commons)是具体可调用的代码集合。框架中大量使用了设计模式。
  • 设计模式 vs. 设计原则:设计原则(如SOLID)是更抽象、更高层的指导思想;设计模式是这些原则在特定场景下的具体实现和体现。例如,工厂模式体现了“依赖倒置”原则。

『面试官追问』

  1. 请结合项目实际,举例说明你用过哪些设计模式?解决了什么问题?(高频)
  2. 单例模式的双重检查锁为什么要加 volatile?饿汉式和懒汉式各有何优劣?
  3. Spring框架中大量使用了哪些设计模式?(如工厂模式创建Bean、代理模式实现AOP、模板方法模式定义流程等)
  4. 设计模式会不会导致过度设计?如何权衡?

【直击痛点】

  • “23种”经典模式:GoF(四人帮)在《设计模式:可复用面向对象软件的基础》一书中归纳了23种基础模式,这是面试常考的数字。它代表了早期对面向对象设计经验的经典总结,但并非上限,后续还有如 MVC、依赖注入等更多模式被广泛认可。
  • 模式的“适用性”:每种模式都有明确的适用场景。滥用模式(如在简单场景使用复杂模式)会导致代码不必要的复杂化,这正是“过度设计”的痛点。关键在于识别出代码中存在的“坏味道”(如大量if/else、类职责过重),再对症下药地选用模式。

【逻辑复现】(以面试高频的单例模式-双重检查锁为例)

  • 目标:实现线程安全且高效的懒加载单例。
  • 逻辑步骤:
    • Step 1: 私有化构造函数,防止外部 new。
    • Step 2: 声明一个 private static volatile 的实例变量。
    • Step 3: 提供公共的 public static 获取方法。
    • Step 4: 在方法内,首先进行第一次检查(if (instance == null)),如果非空则直接返回,避免每次进入同步块,提升性能。
    • Step 5: 如果为null,则进入同步代码块(synchronized)。
    • Step 6: 在同步块内进行第二次检查,防止在等待锁期间已有其他线程完成了初始化。
    • Step 7: 确认实例为null后,执行初始化,并赋值给变量。
    • volatile 关键作用:禁止指令重排,确保其他线程在读取 instance 时,看到的是一个完全初始化好的对象,避免拿到一个半初始化的对象(DCL失效问题)。

【版本差异/演进】

  • 随着编程范式和语言特性的发展,设计模式的应用也在演变。例如:
    • Java中的枚举(Enum)是实现单例模式的最佳实践之一,它由JVM保证线程安全和反序列化安全,比传统的DCL更简洁安全。
    • 函数式编程的兴起,使得策略模式、命令模式等可以通过Lambda表达式更简洁地实现。
    • IoC容器(如Spring)的普及,使得工厂模式的应用从显式编码转变为容器配置和管理。
My avatar

文章看完了,不打算去别的篇章转转吗?👀 感谢你的耐心阅读!如果你有问题想探讨,或者发现了文中的 Bug,请务必通过页脚的链接联系我


More Posts

Comments