欢迎光临
我们一直在努力

《Head First设计模式》读书笔记01: 《Head First设计模式》到底讲了什么?新手怎么学才不会从入门到放弃

作者: andylin02
学习章节: 《Head First设计模式》概览与学习指南
关键词:设计模式, 面向对象, 策略模式, 观察者模式, 装饰者模式, 设计原则, Java


《Head First设计模式》到底讲了什么?新手怎么学才不会从入门到放弃

大家好,我是 andylin02。如果你刚翻开《Head First设计模式》这本书,可能会被它花哨的排版、满篇的图片和看似零散的故事搞得一脸懵。别急,这正是 Head First 系列的魔力——它用大量视觉化、故事化的方式,把枯燥的设计模式讲活。今天这篇长文,我带你从零开始,搞明白这本书的全部脉络、你能学到什么、需要准备什么,以及给出可以直接参考的学习笔记、源码和图解。文末还会预告第一章“策略模式”的精彩内容,让我们一起开启设计模式之旅。

一、这本书到底讲了什么?

想象一下,你刚入职一家游戏公司,老板让你做一款“鸭子模拟器”。你想都没想,设计了一个 Duck 超类,让所有鸭子继承它。一切都很美好,直到老板说:“我们需要鸭子会飞”。你轻松地在 Duck 里加了 fly() 方法——结果,橡皮鸭子也在屏幕上扑棱扑棱飞了起来,全场爆笑。

这就是《Head First设计模式》贯穿始终的核心矛盾:软件唯一不变的就是变化。怎么让代码在需求变动时还能优雅地扩展,而不是牵一发动全身?这本书用一个个类似“鸭子困境”的故事,引出 23个经典设计模式 中最常用、最核心的十几个模式,并让你反复体会背后那些永恒的设计原则。

全书可以分成以下几大块:

  • 设计模式入门与原则(第1章):策略模式,正式带你理解“把变化的部分封装起来”。
  • 观察者与装饰者(第2-3章):让对象之间松耦合通信,以及运行时动态地扩展职责。
  • 工厂模式家族(第4章):把对象创建的过程抽象出来,让代码不再硬依赖具体类。
  • 单例与命令模式(第5-6章):控制唯一实例,以及把请求封装成对象,支持撤销、队列等。
  • 适配器与外观模式(第7章):把不兼容的接口转换得能一起工作,以及提供简化接口。
  • 模板方法与迭代器组合模式(第8-9章):定义算法骨架,以及如何优雅地遍历集合。
  • 状态模式(第10章):让对象的行为随着内部状态改变而改变。
  • 代理模式(第11章):给另一个对象提供一个替身,以控制访问。
  • 复合模式与实战(第12章):MVC 架构就是多种模式的组合运用。
  • 更多模式与设计原则总结(第13-14章):介绍剩余模式,回归设计原则本身。

书中每个模式都采用固定的讲解结构:问题场景 → 直观解决方案的失败 → 设计原则 → 模式正式定义 → 类图 → 代码实现 → 实际应用案例。这种结构很适合初学者跟着思考,而不是被动接受。

二、学好这本书,你能学到哪些关键知识?

如果你认真啃完这本书并手写了所有代码,你将收获一把衡量代码好坏的内在标尺。具体来说:

  • 面向对象设计的九大原则

    • 封装变化
    • 针对接口编程,而不是针对实现
    • 多用组合,少用继承
    • 为交互对象之间的松耦合设计而努力
    • 对扩展开放,对修改关闭(开闭原则)
    • 依赖倒置:依赖抽象,不要依赖具体类
    • 最少知识原则:只和你的密友谈话
    • 好莱坞原则:别调用我们,我们会调用你
    • 单一职责:一个类应该只有一个引起变化的原因
      这些原则比模式本身更重要,它们是模式背后的“心法”。
  • 十几个核心设计模式:策略、观察者、装饰者、工厂方法、抽象工厂、单例、命令、适配器、外观、模板方法、迭代器、组合、状态、代理、复合模式等。掌握它们,你就能看懂大部分优秀框架的源码(比如 Spring 里随处可见的模板方法、策略、代理模式)。

  • 模式分类的全局视野:理解创建型、结构型、行为型三大分类,能够根据问题类型快速锁定可能的模式方向。

  • 真正的面向对象编程思维:不只是会写 class 和 extends,而是懂得如何给对象分配职责,设计弹性的体系。

  • 阅读和绘制 UML 类图的能力,这是开发者之间交流设计思想的通用语言。

  • 三、我需要具备什么基础能力?要准备什么?

    这本书对初学者非常友好,但并不意味着零基础就能直接上手。你需要:

    • Java 基础:能熟练定义类和接口,理解继承、多态、抽象类、方法重写。因为所有示例代码都是 Java,至少要能看懂并运行。
    • 基本的 IDE 使用:推荐 IntelliJ IDEA 或 Eclipse,能新建项目、写类、运行 main 方法。
    • 一颗愿意深究“为什么”的心:如果只满足于跑通代码,你会错过这本书 80% 的价值。

    准备工作清单:

  • 安装 JDK 8 及以上版本,配置好环境变量。
  • 准备一本《Head First设计模式》(第2版更新了 Java 8+ 的 Lambda 示例,更推荐;第1版也行,核心不变)。
  • 准备一个笔记本(或电子笔记),每学完一个模式,用自己的话总结:问题、解决方案、类图、代码关键点、现实类比。
  • 把书中所有代码都亲手敲一遍,不要复制粘贴。报错了就调试,这本身就是学习。
  • 四、有什么注意事项?

    • 不要追求一次全懂:尤其工厂模式那章知识点密集,可以分两天消化。反复阅读,每次都有新感悟。
    • 模式不是银弹:别学完一个模式就到处套,为了模式而模式会让代码更难懂。简单的需求不需要复杂的设计。
    • 优先掌握原则,而非死记类图:类图你可以随时查,但原则是内化的思维习惯。
    • 结合生活类比理解:比如观察者模式就是“报纸订阅”,策略模式就是“选择不同的交通工具上班”。全书充满了这样的比喻,善于利用它们。
    • 第12章 MVC 是集大成者:学完前面所有模式再去看 MVC,你会恍然大悟,原来这些模式可以这样组合。

    五、详细学习文档与读书笔记

    为了帮你建立起清晰的知识框架,我整理了一份超详细的学习导图。首先,让我们看看这十几个模式在整个设计模式版图中的位置:

    #mermaid-svg-qNA5k9PlzVq2Pxhn{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-qNA5k9PlzVq2Pxhn .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-qNA5k9PlzVq2Pxhn .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-qNA5k9PlzVq2Pxhn .error-icon{fill:#552222;}#mermaid-svg-qNA5k9PlzVq2Pxhn .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-qNA5k9PlzVq2Pxhn .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-qNA5k9PlzVq2Pxhn .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-qNA5k9PlzVq2Pxhn .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-qNA5k9PlzVq2Pxhn .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-qNA5k9PlzVq2Pxhn .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-qNA5k9PlzVq2Pxhn .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-qNA5k9PlzVq2Pxhn .marker{fill:#333333;stroke:#333333;}#mermaid-svg-qNA5k9PlzVq2Pxhn .marker.cross{stroke:#333333;}#mermaid-svg-qNA5k9PlzVq2Pxhn svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-qNA5k9PlzVq2Pxhn p{margin:0;}#mermaid-svg-qNA5k9PlzVq2Pxhn .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-qNA5k9PlzVq2Pxhn .cluster-label text{fill:#333;}#mermaid-svg-qNA5k9PlzVq2Pxhn .cluster-label span{color:#333;}#mermaid-svg-qNA5k9PlzVq2Pxhn .cluster-label span p{background-color:transparent;}#mermaid-svg-qNA5k9PlzVq2Pxhn .label text,#mermaid-svg-qNA5k9PlzVq2Pxhn span{fill:#333;color:#333;}#mermaid-svg-qNA5k9PlzVq2Pxhn .node rect,#mermaid-svg-qNA5k9PlzVq2Pxhn .node circle,#mermaid-svg-qNA5k9PlzVq2Pxhn .node ellipse,#mermaid-svg-qNA5k9PlzVq2Pxhn .node polygon,#mermaid-svg-qNA5k9PlzVq2Pxhn .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-qNA5k9PlzVq2Pxhn .rough-node .label text,#mermaid-svg-qNA5k9PlzVq2Pxhn .node .label text,#mermaid-svg-qNA5k9PlzVq2Pxhn .image-shape .label,#mermaid-svg-qNA5k9PlzVq2Pxhn .icon-shape .label{text-anchor:middle;}#mermaid-svg-qNA5k9PlzVq2Pxhn .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-qNA5k9PlzVq2Pxhn .rough-node .label,#mermaid-svg-qNA5k9PlzVq2Pxhn .node .label,#mermaid-svg-qNA5k9PlzVq2Pxhn .image-shape .label,#mermaid-svg-qNA5k9PlzVq2Pxhn .icon-shape .label{text-align:center;}#mermaid-svg-qNA5k9PlzVq2Pxhn .node.clickable{cursor:pointer;}#mermaid-svg-qNA5k9PlzVq2Pxhn .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-qNA5k9PlzVq2Pxhn .arrowheadPath{fill:#333333;}#mermaid-svg-qNA5k9PlzVq2Pxhn .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-qNA5k9PlzVq2Pxhn .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-qNA5k9PlzVq2Pxhn .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qNA5k9PlzVq2Pxhn .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-qNA5k9PlzVq2Pxhn .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qNA5k9PlzVq2Pxhn .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-qNA5k9PlzVq2Pxhn .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-qNA5k9PlzVq2Pxhn .cluster text{fill:#333;}#mermaid-svg-qNA5k9PlzVq2Pxhn .cluster span{color:#333;}#mermaid-svg-qNA5k9PlzVq2Pxhn div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-qNA5k9PlzVq2Pxhn .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-qNA5k9PlzVq2Pxhn rect.text{fill:none;stroke-width:0;}#mermaid-svg-qNA5k9PlzVq2Pxhn .icon-shape,#mermaid-svg-qNA5k9PlzVq2Pxhn .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qNA5k9PlzVq2Pxhn .icon-shape p,#mermaid-svg-qNA5k9PlzVq2Pxhn .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-qNA5k9PlzVq2Pxhn .icon-shape .label rect,#mermaid-svg-qNA5k9PlzVq2Pxhn .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qNA5k9PlzVq2Pxhn .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-qNA5k9PlzVq2Pxhn .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-qNA5k9PlzVq2Pxhn :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    设计模式

    创建型

    结构型

    行为型

    单例模式

    工厂方法模式

    抽象工厂模式

    适配器模式

    外观模式

    装饰者模式

    代理模式

    策略模式

    观察者模式

    命令模式

    模板方法模式

    迭代器模式

    组合模式

    状态模式

    学习路线建议(按章节顺序):

  • 策略模式(入门):理解封装变化与组合优于继承。
  • 观察者模式(松耦合):理解一对多依赖与推送/拉取。
  • 装饰者模式(弹性扩展):理解在不修改原有代码的情况下增加功能。
  • 工厂模式(解耦创建):简单工厂→工厂方法→抽象工厂,逐步演进。
  • 单例模式(全局唯一):经典实现与多线程安全。
  • 命令模式(请求封装):解耦调用者和执行者,支持撤销。
  • 适配器与外观(接口统一):适配器转换接口,外观简化复杂子系统。
  • 模板方法与迭代器组合(算法骨架与遍历):模板方法复用算法,迭代器统一遍历,组合处理树形结构。
  • 状态模式(状态驱动行为):消除冗长的 if-else,状态转换清晰。
  • 代理模式(控制访问):远程代理、虚拟代理、保护代理。
  • 复合模式(MVC 解剖):模式组合的真实案例。
  • 下面我以第一章的策略模式为例,给出完整的 UML 图和源代码,让你提前感受一下书中的学习方式。

    策略模式:从“鸭子困境”学到设计原则

    故事回顾:Joe 的鸭子模拟器里,所有鸭子都会叫、会游泳,但老板不断加需求:有的会飞,有的不会,有的吱吱叫,有的呱呱叫。如果在 Duck 超类里直接实现 fly(),所有子类都继承会飞的行为——橡皮鸭也会飞。如果用接口 Flyable,每个会飞的子类自己实现,导致大量重复代码。怎么办?

    设计原则登场:

    • 找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。
      变化的是“飞行行为”和“呱呱叫行为”,我们把它们分别封装成独立的接口族。
    • 针对接口编程,而不是针对实现。
      鸭子类不关心具体怎么飞,只依赖 FlyBehavior 接口。
    • 多用组合,少用继承。
      每个鸭子“有一个”飞行行为和一个呱呱叫行为,而不是“是一个”固定的飞行器。

    策略模式定义:定义了一系列算法,把它们一个个封装起来,并且使它们可以互相替换。策略模式让算法的变化独立于使用它的客户。

    UML 类图:

    #mermaid-svg-1jHVYCPNRU8oLrJB{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-1jHVYCPNRU8oLrJB .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-1jHVYCPNRU8oLrJB .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-1jHVYCPNRU8oLrJB .error-icon{fill:#552222;}#mermaid-svg-1jHVYCPNRU8oLrJB .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-1jHVYCPNRU8oLrJB .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-1jHVYCPNRU8oLrJB .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-1jHVYCPNRU8oLrJB .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-1jHVYCPNRU8oLrJB .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-1jHVYCPNRU8oLrJB .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-1jHVYCPNRU8oLrJB .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-1jHVYCPNRU8oLrJB .marker{fill:#333333;stroke:#333333;}#mermaid-svg-1jHVYCPNRU8oLrJB .marker.cross{stroke:#333333;}#mermaid-svg-1jHVYCPNRU8oLrJB svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-1jHVYCPNRU8oLrJB p{margin:0;}#mermaid-svg-1jHVYCPNRU8oLrJB g.classGroup text{fill:#9370DB;stroke:none;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:10px;}#mermaid-svg-1jHVYCPNRU8oLrJB g.classGroup text .title{font-weight:bolder;}#mermaid-svg-1jHVYCPNRU8oLrJB .cluster-label text{fill:#333;}#mermaid-svg-1jHVYCPNRU8oLrJB .cluster-label span{color:#333;}#mermaid-svg-1jHVYCPNRU8oLrJB .cluster-label span p{background-color:transparent;}#mermaid-svg-1jHVYCPNRU8oLrJB .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-1jHVYCPNRU8oLrJB .cluster text{fill:#333;}#mermaid-svg-1jHVYCPNRU8oLrJB .cluster span{color:#333;}#mermaid-svg-1jHVYCPNRU8oLrJB .nodeLabel,#mermaid-svg-1jHVYCPNRU8oLrJB .edgeLabel{color:#131300;}#mermaid-svg-1jHVYCPNRU8oLrJB .edgeLabel .label rect{fill:#ECECFF;}#mermaid-svg-1jHVYCPNRU8oLrJB .label text{fill:#131300;}#mermaid-svg-1jHVYCPNRU8oLrJB .labelBkg{background:#ECECFF;}#mermaid-svg-1jHVYCPNRU8oLrJB .edgeLabel .label span{background:#ECECFF;}#mermaid-svg-1jHVYCPNRU8oLrJB .classTitle{font-weight:bolder;}#mermaid-svg-1jHVYCPNRU8oLrJB .node rect,#mermaid-svg-1jHVYCPNRU8oLrJB .node circle,#mermaid-svg-1jHVYCPNRU8oLrJB .node ellipse,#mermaid-svg-1jHVYCPNRU8oLrJB .node polygon,#mermaid-svg-1jHVYCPNRU8oLrJB .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-1jHVYCPNRU8oLrJB .divider{stroke:#9370DB;stroke-width:1;}#mermaid-svg-1jHVYCPNRU8oLrJB g.clickable{cursor:pointer;}#mermaid-svg-1jHVYCPNRU8oLrJB g.classGroup rect{fill:#ECECFF;stroke:#9370DB;}#mermaid-svg-1jHVYCPNRU8oLrJB g.classGroup line{stroke:#9370DB;stroke-width:1;}#mermaid-svg-1jHVYCPNRU8oLrJB .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5;}#mermaid-svg-1jHVYCPNRU8oLrJB .classLabel .label{fill:#9370DB;font-size:10px;}#mermaid-svg-1jHVYCPNRU8oLrJB .relation{stroke:#333333;stroke-width:1;fill:none;}#mermaid-svg-1jHVYCPNRU8oLrJB .dashed-line{stroke-dasharray:3;}#mermaid-svg-1jHVYCPNRU8oLrJB .dotted-line{stroke-dasharray:1 2;}#mermaid-svg-1jHVYCPNRU8oLrJB #compositionStart,#mermaid-svg-1jHVYCPNRU8oLrJB .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-1jHVYCPNRU8oLrJB #compositionEnd,#mermaid-svg-1jHVYCPNRU8oLrJB .composition{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-1jHVYCPNRU8oLrJB #dependencyStart,#mermaid-svg-1jHVYCPNRU8oLrJB .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-1jHVYCPNRU8oLrJB #dependencyStart,#mermaid-svg-1jHVYCPNRU8oLrJB .dependency{fill:#333333!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-1jHVYCPNRU8oLrJB #extensionStart,#mermaid-svg-1jHVYCPNRU8oLrJB .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-1jHVYCPNRU8oLrJB #extensionEnd,#mermaid-svg-1jHVYCPNRU8oLrJB .extension{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-1jHVYCPNRU8oLrJB #aggregationStart,#mermaid-svg-1jHVYCPNRU8oLrJB .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-1jHVYCPNRU8oLrJB #aggregationEnd,#mermaid-svg-1jHVYCPNRU8oLrJB .aggregation{fill:transparent!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-1jHVYCPNRU8oLrJB #lollipopStart,#mermaid-svg-1jHVYCPNRU8oLrJB .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-1jHVYCPNRU8oLrJB #lollipopEnd,#mermaid-svg-1jHVYCPNRU8oLrJB .lollipop{fill:#ECECFF!important;stroke:#333333!important;stroke-width:1;}#mermaid-svg-1jHVYCPNRU8oLrJB .edgeTerminals{font-size:11px;line-height:initial;}#mermaid-svg-1jHVYCPNRU8oLrJB .classTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-1jHVYCPNRU8oLrJB .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-1jHVYCPNRU8oLrJB .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-1jHVYCPNRU8oLrJB :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

    «abstract»

    Duck

    FlyBehavior flyBehavior

    QuackBehavior quackBehavior

    +performFly()

    +performQuack()

    +swim()

    +display()

    +setFlyBehavior(FlyBehavior fb)

    +setQuackBehavior(QuackBehavior qb)

    MallardDuck

    +display()

    RedheadDuck

    +display()

    RubberDuck

    +display()

    «interface»

    FlyBehavior

    +fly()

    FlyWithWings

    +fly()

    FlyNoWay

    +fly()

    «interface»

    QuackBehavior

    +quack()

    Quack

    +quack()

    Squeak

    +quack()

    MuteQuack

    +quack()

    完整源码:

    // ========== 飞行行为接口与实现 ==========
    public interface FlyBehavior {
    void fly();
    }

    public class FlyWithWings implements FlyBehavior {
    public void fly() {
    System.out.println("I'm flying with wings!");
    }
    }

    public class FlyNoWay implements FlyBehavior {
    public void fly() {
    System.out.println("I can't fly.");
    }
    }

    // ========== 呱呱叫行为接口与实现 ==========
    public interface QuackBehavior {
    void quack();
    }

    public class Quack implements QuackBehavior {
    public void quack() {
    System.out.println("Quack! Quack!");
    }
    }

    public class Squeak implements QuackBehavior {
    public void quack() {
    System.out.println("Squeak! Squeak!");
    }
    }

    public class MuteQuack implements QuackBehavior {
    public void quack() {
    System.out.println("<< Silence >>");
    }
    }

    // ========== 鸭子抽象类 ==========
    public abstract class Duck {
    FlyBehavior flyBehavior;
    QuackBehavior quackBehavior;

    public void performFly() {
    flyBehavior.fly();
    }

    public void performQuack() {
    quackBehavior.quack();
    }

    public void swim() {
    System.out.println("All ducks float, even decoys!");
    }

    public abstract void display();

    // 动态设定行为,增加弹性
    public void setFlyBehavior(FlyBehavior fb) {
    this.flyBehavior = fb;
    }

    public void setQuackBehavior(QuackBehavior qb) {
    this.quackBehavior = qb;
    }
    }

    // ========== 具体鸭子子类 ==========
    public class MallardDuck extends Duck {
    public MallardDuck() {
    flyBehavior = new FlyWithWings();
    quackBehavior = new Quack();
    }

    public void display() {
    System.out.println("I'm a real Mallard duck");
    }
    }

    public class RubberDuck extends Duck {
    public RubberDuck() {
    flyBehavior = new FlyNoWay();
    quackBehavior = new Squeak();
    }

    public void display() {
    System.out.println("I'm a rubber duckie");
    }
    }

    // ========== 测试运行 ==========
    public class MiniDuckSimulator {
    public static void main(String[] args) {
    Duck mallard = new MallardDuck();
    mallard.display();
    mallard.performQuack();
    mallard.performFly();

    Duck rubber = new RubberDuck();
    rubber.display();
    rubber.performQuack();
    rubber.performFly();

    // 动态改变行为——这才是策略模式的威力
    rubber.setFlyBehavior(new FlyWithWings());
    rubber.performFly(); // 哇!橡皮鸭装上火箭引擎飞起来了!
    }
    }

    运行这段代码,你会直观地看到:我们通过组合行为对象,轻松搭建出不同行为的鸭子,并且能够在运行时动态切换行为。这就为后续的观察者模式、装饰者模式打下了坚实的思维基础。

    全书模式速查笔记(简要)

    模式一句话理解关键设计原则
    策略模式 封装算法,使其可互换 封装变化,多用组合
    观察者模式 主题状态改变时通知所有观察者 松耦合,推/拉数据
    装饰者模式 动态给对象添加职责 对扩展开放,对修改关闭
    工厂方法 定义创建对象的接口,让子类决定实例化哪个类 依赖倒置,针对抽象编程
    抽象工厂 创建一系列相关对象,而不指定具体类 依赖倒置
    单例模式 确保一个类只有一个实例 全局访问点,懒/饿汉加载
    命令模式 把请求封装为对象 解耦调用者与执行者,支持撤销
    适配器模式 把不兼容的接口转换为客户端期望的接口 转换接口,兼容旧代码
    外观模式 提供统一的高层接口,简化子系统使用 最少知识原则
    模板方法 在方法中定义算法骨架,将部分步骤延迟到子类 好莱坞原则
    迭代器模式 提供顺序访问聚合对象元素的方法,而不暴露内部表示 单一职责,遍历与集合分离
    组合模式 将对象组合成树形结构以表示“部分-整体”层次 统一处理单个对象和组合对象
    状态模式 对象内部状态改变时改变其行为 把状态封装为独立类
    代理模式 给另一个对象提供一个替身,控制对它的访问 控制访问,延迟加载

    你可以把它打印出来,贴在学习桌前,每学完一个模式就自己填上实例和理解,效果极佳。

    六、总结

    《Head First设计模式》绝对不是一本让你“读完就忘”的教科书,它是一本训练营手册。它逼迫你不断思考软件变化之源,并通过手把手的故事和代码,把设计原则烙进你的思维里。

    从策略模式起,你就开始学会“把变化的地方揪出来关进笼子里”。后续每一个模式,都是在不同场景下对这个核心思想的进一步演绎。好好跟着书中的节奏走,别跳步,你会发现:六个月后,当你回看自己过去写的“一锅粥”代码时,会不由自主地皱起眉头,并脑海中自动浮现出一个合适的模式来重构它。那个时刻,你就真正入门了。

    七、下篇预告:第一章·策略模式深度剖析

    今天我们整体梳理了《Head First设计模式》的全貌,并给出了策略模式的初体验。下一篇文章,我将带你正式走进第一章——策略模式,我会逐句讲解鸭子模拟器的开发历程、每一个设计决策背后的得失,以及如何将策略模式应用到真实的项目(比如支付系统中的不同支付策略)。还会带来更多变体练习和课后思考。敬请期待!


    本文为个人学习笔记,仅用于知识分享。如有错误,欢迎指正。
    👍🏻 点赞 + 收藏 + 分享,让更多开发者看到这篇深度解析!❤️ 如果觉得有用,请给个赞支持一下作者!

    赞(0)
    未经允许不得转载:171主机测评 » 《Head First设计模式》读书笔记01: 《Head First设计模式》到底讲了什么?新手怎么学才不会从入门到放弃
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址