设计模式速记法:从背概念到建立思维坐标的实战指南

发布时间:2026/9/16 7:47:13
设计模式速记法:从背概念到建立思维坐标的实战指南 设计模式这东西只要你接触过一段时间肯定有过这种体验看的时候感觉全懂合上书第二天就忘了一大半面试前一晚背得滚瓜烂熟面试官换了个场景提问瞬间不知道用哪个期末复习的时候二十多个模式排成一列脑子里全是“工厂、抽象工厂、建造者……”长相都差不多的影子。这几年我带过不少实习生、也帮人做过面试突击辅导发现大多数人不是不努力而是把设计模式当成了“知识点”在死记硬背没有真正把它变成一套可以随时调用的“思维工具”。这篇文章我就把自己一直用的这套“设计模式速记”方法整理出来从一个实际项目里打磨过的角度告诉你哪些模式必须熟练掌握、每个模式最核心的一句话本质是什么、复习的时候怎么在几分钟之内把整个框架串起来以及考试和面试里最容易踩的坑。这套方法是我在实际开发项目里反复用过的也在给团队做技术分享的时候验证过不是从哪本书上抄下来的理论框架。它解决的是三个最具体的问题第一怎么用最短的时间建立起设计模式的整体坐标系不至于学了后面忘了前面第二每个模式到底在解决什么问题用一句话说清楚而不是背一堆“定义类图示例代码”第三遇到面试题或者大作业需求的时候怎么快速判断该用哪个模式以及为什么是它而不是别的。1. 从“背模式”到“建坐标”先搞懂设计模式到底在解决什么很多人的第一个误区是想把二十三个经典模式一个个背熟。这个思路从一开始就走偏了。设计模式不是一个一个孤立的知识点它是一套关于“怎么让代码在变化面前更稳”的经验总结。如果你抓住了这个核心你会发现所有模式背后其实就两件事在反复出现一个是“找出变化封装变化”另一个是“面向接口编程而不是面向实现编程”。1.1 七大设计原则才是真正的“心法”记住GOF那二十三个模式之前我建议你先花一个小时把七大设计原则弄明白。为什么因为原则是“为什么”模式是“怎么做”。你只有先知道了设计要往哪个方向走才能理解为什么某个模式要那样搭结构。七大原则我用一个口诀记“开里依单迪合”。对应的是开闭原则、里氏替换原则、依赖倒置原则、单一职责原则、迪米特法则、合成复用原则加上一个接口隔离原则。这里面最核心的是开闭原则对扩展开放对修改关闭。说人话就是以后要加新功能的时候尽量不碰已经写好并且测试过的老代码而是通过加新代码来实现。举个例子你就明白了。假设你给一家餐厅写点餐系统一开始只支持现金支付。你写了一个CashPay类调用方直接new CashPay()然后pay()很正常。后来老板说要支持微信支付你要怎么改如果原来的代码里到处都是new CashPay()就得一个一个去改这就是“修改关闭”没做好。如果你一开始定义了一个IPay接口调用方只依赖接口那加微信支付就只是新增一个WechatPay类实现IPay原来的代码一行都不用动。里氏替换原则也很关键它是说子类必须能够替换掉它的父类并且程序的行为不出问题。这个原则直接决定了你继承用不用得对。很多人写代码特别喜欢继承看到两个类有点像就抽个父类出来结果子类重写父类方法的时候把逻辑改得面目全非。等到哪天要替换子类的时候程序直接崩了。我见过一个真实案例有个项目里Square(正方形)继承了Rectangle(长方形)然后重写了setWidth方法保证长宽相等。看着挺好的结果做面积计算的代码传了个Rectangle进来运行的时候设了宽和长面积算出来是错的——因为里氏替换被破坏了。这就是看起来“合理”的继承实际是个坑。依赖倒置原则简单说就是高层模块不应该依赖低层模块两者都应该依赖抽象。翻译成人话业务层不要直接依赖工具类、具体实现类而是依赖抽象接口。这个原则跟开闭原则是配套的你只有依赖了抽象才可能做到对扩展开放。这几个原则相互之间是有关联的单一职责是让类有明确的“一个理由”接口隔离是让接口尽量小而专迪米特法则告诉你要“少跟陌生人说话”合成复用原则是提醒你优先用组合而不是继承。1.2 二十三个模式的“三维坐标”创建型、结构型、行为型原则有了接下来就是模式主体的分类。二十三个模式分成三大类很多人只是把这个分类背下来就没了。但仔细想想这个分类本身就有极强的记忆价值因为它其实对应着软件设计的三个维度创建型模式5个解决“对象怎么产生”的问题。你在什么场景下用什么方式new一个对象。结构型模式7个解决“对象怎么组合”的问题。类与类、对象与对象之间怎么组成更大的结构。行为型模式11个解决“对象之间怎么协作”的问题。责任怎么划分、算法怎么封装、状态怎么流转。我建议你把这个分类当成坐标系来记。拿到一个需求先问自己三个问题这个场景的重点是在“怎么创建对象”还是在“怎么组织对象关系”还是在“怎么处理对象之间的交互”定位到其中一个维度之后再在维度内部去找具体的模式命中率会高得多。举一个很典型的例子你需要一个全局唯一的配置管理器。第一步判断重点在“对象怎么产生”锁定创建型第二步需要一个类只允许一个实例——单例模式搞定。整个过程不到十秒钟。但如果不懂分类你可能看哪个模式都像卡在那里半天选不出来。还有一个容易被忽略的点三大类不是完全割裂的同一个复杂的项目里经常会多个模式配合使用。比如一个管理系统里你可能用工厂方法创建不同类型的报表用组合模式把报表和子报表组织成树形结构再用观察者模式让数据变动时自动刷新报表用策略模式切换不同的统计算法。这就是模式组合的典型场景。你在复习的时候与其一个个孤立地背不如想想怎么把三四个模式串成一个微型项目这样记忆会牢固得多。关于每个模式的数量和名字我附一个速记清单你可以把它作为自检表看自己是不是能对着表把每个模式的核心思想在三句话以内讲清楚类型模式名称一句话本质创建型简单工厂 / 工厂方法 / 抽象工厂把new对象的逻辑集中起来让调用方和具体类解耦差别在于工厂的抽象粒度创建型单例模式保证一个类只有一个实例并提供一个全局访问点创建型建造者模式把一个复杂对象的构建过程和它的表示分离同样的构建过程能造出不同的产品创建型原型模式通过复制现有对象来创建新对象而不是通过new结构型适配器模式让两个接口不兼容的类可以一起工作加一个中间转换层结构型装饰器模式动态地给一个对象添加额外的职责比继承更灵活结构型代理模式不直接访问真实对象通过一个替身来控制访问可以在访问前后加逻辑结构型组合模式把部分和整体的关系用树形结构表示让客户端可以一致地处理单个对象和组合对象结构型外观模式给一堆复杂的子系统提供一个统一的简单入口结构型桥接模式把抽象部分和实现部分分离让它们可以独立变化结构型享元模式通过共享细粒度对象来节省内存大量相似对象只保留一份共享状态行为型策略模式定义一族算法把它们封装起来让它们可以互相替换行为型观察者模式对象之间一对多依赖一个对象状态变了所有依赖它的对象都收到通知行为型模板方法模式父类定义算法的骨架把一些步骤延迟到子类中实现行为型责任链模式多个对象都有机会处理请求把它连成一条链沿着链传递直到有人处理行为型状态模式对象的行为取决于它的内部状态状态变了行为也跟着变行为型命令模式把请求封装成对象从而可以用不同的请求对客户端进行参数化行为型迭代器模式提供一种顺序访问聚合对象内部元素的方法又不暴露内部结构行为型中介者模式用一个中介对象来封装一系列对象之间的交互让它们不必显式互相引用行为型备忘录模式在不破坏封装的前提下捕获并保存对象的内部状态以便之后恢复行为型解释器模式给定一门语言定义它的文法表示并提供一个解释器来解释语言中的句子行为型访问者模式在不改变元素类的前提下定义作用于这些元素的新操作这张表你先留个印象下面我会挑最核心的十几个把速记要点展开讲透。2. 创建型模式速记别让“new”毁了你的代码创建型模式一共五个算上常被提到的简单工厂其实是六个简单工厂不属于GOF 23种但考试和面试都常考主要解决一个核心痛点new这个动作太“硬”了。你在代码里写new A()就把A这个具体类和调用方死死绑定了。创建型模式就是想办法把“怎么new”“new什么”从调用方的代码里抽出去。2.1 工厂三兄弟从简单工厂到抽象工厂差在哪工厂模式是创建型里的重点也是考试和面试的高频区域。我给你一条清晰的升级路线简单工厂 → 工厂方法 → 抽象工厂。简单工厂是最直白的把创建逻辑放在一个工厂类里传个参数进去工厂帮你判断该返回哪个产品。它本质上是“把一堆if-else收拢到一个地方”。优点是好用、好写缺点是工厂类的职责太重了每加一个新品就要改工厂的if-else违背开闭原则。考试里如果问你简单工厂的缺点答案就在这。工厂方法模式的思路是把工厂抽象化定义一个抽象的Factory接口每个具体产品对应一个具体工厂。比如PizzaFactory是个抽象类下面有CheesePizzaFactory、VeggiePizzaFactory。这样新加产品的时候只要新增一个工厂类不用改老代码。代价是类多了很多每个工厂基本就是“死磕”一个产品。抽象工厂模式继续往前走一步它不是为了创建某一个产品而是为了创建“一族”相关的产品。比如你要做一个跨平台的界面库Windows风格下有WinButton和WinTextMac风格下有MacButton和MacText。这时候抽象工厂UIFactory有两个实现类WindowsFactory和MacFactory每个实现类负责创建一整套配套产品。这样能保证产品族的一致性从WindowsFactory出来的必然是一套Windows风格的东西不会出现Windows按钮配Mac文本框的错乱。速记的时候抓住一条主线简单工厂“一夫当关”工厂方法“各管各的”抽象工厂“成套定制”。再配一个记忆锚点简单工厂改代码工厂方法加代码抽象工厂换整套。2.2 单例模式饿汉、懒汉、双重检查锁单例模式是我在面试里问得最多的一个因为代码简单但坑多。它的核心是一个类全局只有一个实例。两种最常见的写法你要刻在脑子里。饿汉式类加载的时候就创建实例天然线程安全缺点是类一加载就占着内存。懒汉式第一次用的时候才创建实例。单线程时代直接写个懒汉没问题多线程时代就得加处理不然两个线程同时进来就可能创建出两个实例。经典写法是双重检查锁先判断为null再进同步块进了同步块再判一次null然后用volatile修饰实例防止指令重排。考试或者面试里经常问“单例模式有什么问题”很多人只会说“线程安全”。其实更重要的是容易被滥用一个类全局唯一意味着它变成了隐式的全局变量测试不好做类与类之间的依赖也不直观。而且万物皆可单例的话实际上你就把整个项目的生命周期耦合死了。我的建议是配置管理、连接池、日志写入这种“天然就应该全局只有一份”的用单例业务上觉得“好像用不着多个”就上单例的要谨慎一点。2.3 建造者模式和原型模式应对“复杂对象”和“昂贵创建”建造者模式很多初学者不太能理解其实它就类似于你在餐厅点餐你自己不用关心菜是怎么做出来的你只向服务员Builder交代——我要什么样的主食、什么样的配菜、什么样的饮料最后交给厨师Director一起做出来。它适合那些构造参数特别多、对象构建步骤比较固定的场景。比如一个富文本编辑器一个Document对象可能有字体、颜色、行距、页边距、水印等等几十个设置项如果全塞在构造函数里调用方得疯掉。用建造者链式调用就非常爽new DocumentBuilder().setFont(微软雅黑).setColor(red).setLineHeight(1.5).build()。原型模式的记忆点特别简单不重新new而是通过clone()复制一份。它的核心价值是省去重复的创建和初始化过程。比如你有一个已经配置好的报表模板对象想要十个相似但个别字段不同的你用原型模式clone一下改改差异字段就行。Java里实现原型模式记得实现Cloneable接口不然运行时会抛CloneNotSupportedException这是个经典坑。另外还要注意深拷贝和浅拷贝的问题如果对象内部还有引用类型的成员变量直接clone()复制的是引用改动会互相影响这种情况需要自己实现深拷贝逻辑。3. 结构型模式速记类和对象怎么“搭积木”创建型解决的是“怎么造对象”结构型解决的是“对象造出来之后怎么摆、怎么组”。我用一句大白话总结这一类的核心思想在尽量不动原有代码的前提下把类或对象组合成更大的结构。3.1 适配器模式与装饰器模式名字像用处完全不一样适配器和装饰器是很多学生容易混淆的一对。它们结构上有点类似——都是包一层但意图截然不同。适配器模式的出发点是“接口不兼容”。典型场景你在接入第三方支付SDK的时候对方的接口叫createPayment()你的系统里统一用的是pay()直接调肯定不行你就写一个适配器类内部调用第三方SDK对外暴露pay()。客户端的代码不用改第三方SDK的代码也不用改中间加一层“翻译官”。记这个模式的锚点就是充电器转换头——你的设备是Type-C口墙上是USB-A口加一个转换头两边就都对上了。装饰器模式的核心是“增强功能但不改原有类”。它跟适配器的最大区别是适配器是把A接口“翻译”成B接口装饰器是不改接口只是在调用前后动态地加职责。最经典的就是Java IO流new BufferedReader(new FileReader(a.txt))BufferedReader就是个装饰器给FileReader增加了缓冲功能。考试里常问它和继承的区别继承是在编译期静态决定装饰器是运行期动态组合想加什么功能就用装饰器一层层包上去灵活性高得多也不会造成类爆炸。3.2 代理模式别小看这个“替身”代理模式的关键词是“控制”。给它加一个速记锚点——明星和经纪人你联系明星之前经纪人会先过滤一下你的请求谈好了排期你再见到真人。这个中间过程就是代理做的事情。代理和装饰器结构上很像很多人又搞混了。区分要点在意图装饰器是“增强”它做完事情之后对象本身的能力被加了buff代理是“控制”它决定要不要让客户端访问真实对象以及在访问前后要插入什么权限校验、日志记录、延迟加载之类的横切逻辑。Spring AOP的底层就用到了动态代理所以这东西不仅是理论考点实际框架里处处都是。3.3 组合模式树形结构的天然表达组合模式特别直观所以也好记它适合表示“部分-整体”的层次结构。文件系统就是最贴切的例子一个文件夹里有文件也有子文件夹子文件夹里又有文件和子文件夹……对于客户端来说操作一个文件和操作一个文件夹应该尽量一致这样代码写起来才统一。大作业和考试里典型的题目就是“设计一个公司组织架构”总公司下有大部门大部门下有小组小组下有员工。每个人都有一个display()方法叶子节点直接显示自己非叶子节点先显示自己再遍历调用子节点的display()。组合模式的精髓就是让叶子节点和容器节点实现同一个接口代码对两者一视同仁。实际工作里菜单系统、权限目录树、XML/JSON解析树都会用组合模式的思想。注意一个坑如果设计和业务过分追求“一致”导致容器节点和叶子节点的职责差异太大接口会变得很臃肿。这时候可以考虑安全组合模式把管理子节点的方法只放在容器节点里牺牲一部分一致性换取安全性。3.4 外观模式与桥接模式一个“做减法”一个“做分离”外观模式特别容易上手它的核心思想就是“给复杂系统一个简化入口”。比如你开了一家电影院要看电影需要开投影仪、开音响、拉幕布、调灯光。你不可能每次手动去操作所有设备于是你搞了一个“一键观影”按钮点一下后台把所有设备都按顺序打开。这个按钮就是外观。日常开发里很多Service层的方法就是在做这件事把一堆底层组件的调用封装起来对外暴露一个干净利落的入口。这个模式不改变底层系统只提供一个“门面”所以也叫门面模式。桥接模式是结构型里比较难理解的一个核心是“抽象和实现分离”。我记它的一个锚点是“笔和颜料”毛笔有大号、小号颜料有红、蓝、黑你组合出来大号红笔、小号蓝笔……如果把“笔的型号”和“颜料颜色”各自抽象成两个维度并独立变化中间通过组合的方式搭起来这就是桥接。考试里有一个特别典型的桥接案例跨平台消息发送。系统有普通消息和加急消息抽象维度可以用短信发送也可以用邮件发送实现维度。两个维度交叉就有4种组合。如果用继承你会搞出普通短信、普通邮件、加急短信、加急邮件4个类以后每加一种消息类型或者一种发送渠道类都会爆炸。用桥接模式你只需要两个抽象分别是消息类型和消息渠道客户端自由组合扩展性天差地别。享元模式在考试里出现的频率不算最高但概念要知道它通过共享来减少创建对象的数量。最经典的例子是围棋里的黑白棋子——棋盘上几千个落子但本质上只有黑白两种棋子对象位置信息单独存储。String常量池、Integer缓存、线程池都是享元思想的应用。4. 行为型模式速记对象之间的“智慧协作”行为型模式数量最多一共11个也是最容易让人“背了后面忘了前面”的重灾区。我的经验是不要按顺序背而是按“高频场景”来分组记忆。4.1 策略模式把“算法”从业务代码里拎出来策略模式是行为型里面试出现率最高的一个。它的核心词是“替换”定义一族算法把它们各自封装起来让它们可以互相替换算法的变化不影响使用算法的客户端。你在实际项目里大概率写过这种代码根据不同的用户等级计算折扣满500减50、会员打8折、VIP打7折写一堆if-else。if-else本身没错错的是每加一种等级就要改这段核心业务代码容易改错也违背了开闭原则。策略模式的做法是定义一个DiscountStrategy接口每种折扣写一个实现类再让上下文(Context)持有策略接口运行时动态传入具体的策略。我给你的速记口诀是“策略模式不是消灭了if-else而是把if-else从业务代码搬到了工厂/配置里”。这句话非常有用面试的时候你这么说会显得你是真懂而不是在背概念。配一个生活化类比手机地图的出行方式——你输入目的地它根据你选的是驾车/公交/骑行用不同的算法规划路线核心的目的地查找逻辑不变变的只是“出行算法策略”。4.2 观察者模式发布-订阅的那点事观察者模式也是高频中的高频核心词是“通知”。微博的“关注”机制就是最好的例子你关注了一个博主博主发微博所有粉丝都能收到动态你不关注了就收不到。这个模式有两个关键角色主题(Subject)和观察者(Observer)。主题持有一个观察者列表自己状态变化时遍历列表调用每个观察者的更新方法。最需要注意的坑有两个一是主题和观察者之间的循环依赖A观察BB又观察A一个状态变化可能引发无限循环二是观察者数量太多或者更新逻辑太重主题一旦通知就会阻塞很久。所以在实现的时候要谨慎设计通知的粒度必要的时候用异步通知避免“一个对象变了整个系统跟着抖三抖”。GUI事件监听、消息队列的发布订阅模型、监听器模式底层都是观察者的思想。你在简历上写到“使用消息队列解耦”面试官很可能就会追问一句消息队列的发布订阅和观察者模式有什么关系这个问题你要是能答出“观察者是进程内的同步/异步通知消息队列是跨进程的可靠消息投递两者思想一脉相承但消息队列多了持久化、回溯、削峰等能力”面试官会觉得你Level完全不一样。4.3 模板方法模式父类定骨架子类填细节模板方法模式是最“像继承”的模式它的核心词是“骨架”。父类定义一个算法流程里面某些步骤是固定的某些步骤是抽象的、留给子类实现的。给你一个生活化类比煮速冻饺子和煮手擀面大流程都是“烧水→下锅→煮熟→捞出来”但“下锅后要不要加凉水、煮多久”这些细节各自不同。这就叫父类锁定骨架子类覆盖细节。很多框架里都有模板方法的身影Spring的JdbcTemplate执行SQL的流程是固定的获取连接→执行语句→处理结果→关闭连接里面“怎么处理每一行数据”这一步骤交给子类的回调去实现。考试里它还有一个经典对比题模板方法和策略模式的区别。记住一条主线——模板方法是“继承固定流程”子类是继承关系算法骨架被定了策略模式是“组合算法替换”客户端完全替换整个算法不涉及继承骨架。4.4 责任链模式和状态模式两种特别容易记乱的状态机思路责任链模式的记忆锚点是“审批流程”。你提交一个报销单金额小于1000组长批小于5000经理批超过5000总监批。这个申请沿着一条链传递直到某个节点处理。好处是发起者不用知道谁最终能处理也不需要改一堆if-else知道“我的单子该给谁”职责天然解耦。如果把责任链再扩展一下它就变成了FilterChain过滤器链Java Web里的Filter就是标准实现Spring MVC的拦截器也是。所以这个模式非常实用不是那种只在考试里出现的概念。状态模式的核心词是“状态决定行为”。一个对象在不同状态下同一行为的表现完全不同。最经典的例子是订单状态待付款状态下点“支付”能成功已发货状态下再点“支付”就报错。用大量if-else可以写但状态一多逻辑就会缠成一团乱麻。状态模式把每个状态封装成一个类状态之间的切换逻辑放在了状态类内部代码结构清晰而且新增状态时不用改动大段历史逻辑。有一个很容易混淆的点状态模式和策略模式的类图非常像。区分方式是看意图——策略模式是“算法族可以互相替换客户端主动选择”状态模式是“状态内部自动流转客户端无感知”。策略再像、状态再像本质上是一枚硬币的两面策略是主动切换状态是被动流转。4.5 命令模式、迭代器模式、备忘录模式等最低限度的记忆要求对于不是主要考点的行为型模式我建议不用背太深但要做到“看到类图能认出来、给需求能说出意图对应哪几个模式”。命令模式的核心是把请求封装成一个对象这样你可以把请求排队、记录日志、支持撤销。类比就是餐厅里的“服务员记菜单”顾客不用直接跟厨师喊而是把“要什么菜”写在小票上交给厨师小票就是命令对象小票攒一摞还能排队厨房还能根据小票追溯历史。Jenkins的构建任务、操作系统的操作记录都有命令模式的影子。迭代器模式的核心是“遍历与容器解耦”。为什么for-each能用因为集合实现了Iterable接口提供了统一的迭代方式。这样客户端不关心底层是数组还是链表反正都能用同一种方式遍历。记它的锚点就是医院体检的排队叫号系统——你不关心前面排的是谁、从哪个队列来的你只关心叫到自己。备忘录模式是“存档/回档”适合做撤销功能的场景。最简单的类比就是游戏存档打Boss之前存个档挂了之后读档重来。实现的时候要注意大对象复制带来的内存开销生产环境里通常不会保存全量状态而是保存差异或压缩快照。剩下的中介者、解释器、访问者三个模式记一个最基本的场景就行中介者解决“对象网状交互”的问题可以用楼管大妈帮住户传话这个例子帮助记忆解释器用来实现某个特定语言/规则的解释正则表达式就是一个典型应用访问者解决“不影响元素类的前提下增加新的操作”经典案例是编译器里AST上的语法检查、类型检查、代码生成但日常业务开发里用得很少能说出案例即可。5. 考前冲刺与面试实战用“一句话识别法”快速定位模式速记的最终目的是在考场上、面试现场快速给出正确答案。我把自己一直用的实战方法分享出来这套方法叫“一句话识别法”拿到题目不要一上来就背定义先问自己三个连环问题这个场景的重点是“创建对象”还是“组织结构”还是“对象协作”在这个维度里最核心的矛盾是什么——是想解耦创建逻辑想不改变原有代码就增强功能还是想让多个对象协同工作的时候不互相直接依赖针对这个核心矛盾模式的名字基本就浮出水面了。我整理了一个面试/考试高频场景速查表你可以把它当作“刷题前的思维导图”业务场景核心矛盾首选模式日志管理器要全局唯一保证全局只有一个实例单例模式多种数据库连接方式切换运行时替换数据库访问算法策略模式新建一种支付方式老代码尽量不改对扩展开放、避免改老代码工厂方法模式第三方接口不兼容但不想改它的代码解决接口不一致适配器模式给类加权限校验/日志但不想动原逻辑在原有功能上叠加横切逻辑代理模式 / 装饰器模式无限套娃的树形菜单统一处理部分与整体组合模式用户修改资料后多个模块需要同步更新一对多通知解耦观察者模式一套完整报销流程不同金额走不同审批人请求按顺序传递、解耦发送者和接收者责任链模式复杂SQL执行流程固定只需定制结果处理固定骨架、定制变化步骤模板方法模式对象在不同状态下有完全不同的行为状态转移决定行为减少if-else状态模式复杂子系统只想暴露一个简单入口降低客户端使用成本外观模式再补一个你可能在笔试里遇到的点给你一段代码让你画类图判断是什么模式。这个技巧也很简单看到一个接口、多个实现类然后有一个Context类持有接口引用并且Context的方法内部调用了接口的方法——十有八九是策略模式。看到父类定义了方法骨架方法内部调用了若干个抽象方法——模板方法模式。一个类聚合了一堆同样接口的对象递归调用它们的方法——组合模式。一个类持有自己同一类型实例的引用并且方法里先处理自己再调用那个引用——责任链模式。看到两个接口各自有多个实现类其中一个接口的实现里持有另一个接口的引用——桥接模式。说白了判断模式的本质就是看类图里的“关系”继承、实现、聚合、组合、依赖每一种关系对应了一种“意图形态”。复习的时候我强烈建议你不要只盯着文字定义而是把每一个模式的类图画一遍。画图不要求精美关键是你能自己把接口、实现类、关系的箭头标对。为什么这个动作特别有效因为考试和面试里模式识别题最终考的都是类图关系你平时画多了看到陌生题就能条件反射地捕捉到关系特征。6. 设计模式速记的常见陷阱与避坑指南我见过了太多人在设计模式上投入了大量时间却收效甚微问题往往不是出在“记不住”而是出在几个非常典型的误区上。这些坑我自己也踩过所以专门整理出来希望能帮你绕开。6.1 背了一堆模式却不知道何时该用这是最常见的问题。很多人的学习路径是每个模式背定义、背类图、背代码示例感觉自己都会了。但到了一个大作业或者真实需求里就完全懵了不知道怎么选。原因在于定义和类图是“静态知识”而选型是一种“动态决策能力”。想培养这个能力最有效的方法就是我前面说的“三维坐标核心矛盾”法。拿到需求先分类分类完再找矛盾。你还需要刻意练习随便想一个需求比如“点餐系统”“教务管理系统”“停车场计费系统”然后试试用你学过的模式去重新设计一遍。这种练习做十次比你抄十遍代码都管用。我在带人的时候经常让他们把需求用文字描述再用模式去重写设计思路效果立竿见影。设计模式的学习最终要落到“从需求到设计”的转换能力上而不是“记下这些模式”。6.2 为了模式而模式把简单问题复杂化设计模式是来解决“变化”的如果一段代码将来根本不需要变化用设计模式反而画蛇添足。比如业务规则里明确“付费方式只有现金”你非套一个策略模式搞一堆接口和实现类那不仅没有降低复杂度反而增加了维护成本。我见过最夸张的一个例子是有人为了实现“计算一个数是不是偶数”这个小算法硬生生套了一个策略模式接口、两个实现类、一个Context写了五行代码解决问题的事搞出了十几个文件。过度设计这件事资深工程师看到会直接摇头。它带来的问题是整个项目的抽象层次越来越深接手的人需要一层层去跳才能看懂这段代码最终理解了发现只为了一个“if (n % 2 0)”。所以面试的时候你还要展现一种判断力——在“简单可扩展”和“过度设计”之间把握分寸感。一个合格的说法是“这个场景目前没有变化点所以先用最简单的方式实现等出现第二个变体的时候再考虑抽象。”6.3 只记住模式名说不出来龙去脉面试官问“你用过哪些设计模式”的时候很多人会像报菜名一样报出一串然后面试官随便挑一个接着问“这个模式解决的是什么问题解决了什么问题代价是什么”就卡壳了。这是典型的“背名不背实”。你应该怎么应对不要只记住模式名而是永远围绕“为什么用、怎么用、代价是什么”三件套来讲。比如你简历上写了“使用单例模式管理全局配置”就要能接着回答为什么用单例——配置要全局一致单例怎么保证线程安全——用了双重检查锁加volatile单例有什么代价——难以测试、隐式依赖、可能成为并发瓶颈如果不用单例会怎样——每个类各读一份配置必然出现数据不一致。这套追问链条能走通才说明你真的理解了这个模式而不只是在报菜名。我在面试里最常听到的差评回答就是背概念好评回答就是讲真实项目里踩过的坑和权衡取舍。6.4 常见问题速查表最后再放一个速查表把一些容易踩的问题集中列出。我标准的说法是平时可以拿它来自测看自己能不能不看资料就解释清楚。问题核心要点避坑建议简单工厂和工厂方法有什么区别简单工厂把创建逻辑集中在一个类里工厂方法把创建逻辑下放到多个子工厂新增产品时工厂方法不需要改老代码简单工厂需要改代理模式和装饰器模式的区别都是加一层代理偏“控制”装饰器偏“增强”看意图不要只看类图抽象工厂和工厂方法的区别工厂方法创建单个产品抽象工厂创建一族相关产品出现“配套一致性”需求如Windows风格全家桶优先抽象工厂策略模式和状态模式的区别策略是主动换算法状态是被动随状态流转客户端是否感知状态切换是重要判断依据单例模式一定是线程安全的吗饿汉安全懒汉不处理则不安全懒汉用双重检查锁volatile组合模式和继承的关系组合模式不是用继承解决问题而是用树形结构组织“部分-整体”优先用组合而非继承是合成复用原则的核心责任链模式和观察者模式的区别责任链是“链式传递一人处理”观察者是“广播通知全员响应”在“谁来处理”和“谁要感知”之间选型Java里深拷贝还是浅拷贝原型模式默认是浅拷贝有引用类型成员变量时要手动实现深拷贝设计模式这个东西你说它难它其实就二十几个套路翻来覆去就那些关系你说它简单它又要求你把二十几个套路灵活应用在千变万化的业务场景里没有一个放之四海而皆准的答案。我自己这几年最大的体会是设计模式最好的学习方式不是“背”而是“用”——把它当成你工具箱里的工具先掌握每个工具的一两个经典应用场景然后在项目里遇到类似问题时自然地掏出来试试。等你用了几次就会发现在某个需求场景里你几乎是条件反射地想到了某个模式而且每一步的原因都能说得明明白白——到这个时候你才算是真的“速记”成功了。最后分享一个小技巧复习的时候不要按“创建型-结构型-行为型”这种顺序从头看到尾而是打乱顺序随机抽一个模式强迫自己在一分钟内说清楚它的“一句话本质、代码结构核心、典型应用场景、和它最容易混淆的模式”。如果每个模式你都能在一分钟之内走完这四个问题考场上和面试间里基本上就不会慌了。这套速记法如果对你有帮助你可以把它整理成自己的复习卡片反复用直到形成肌肉记忆。