设计模式 22 · 三个冷门模式:中介者、访问者、解释器
行为型的最后三个模式——中介者(Mediator)、访问者(Visitor)、解释器(Interpreter)——我们放在一篇里集中讲。为什么合并?因为它们是二十三式里最冷门、适用面最窄的三个:中介者容易被滥用成上帝类,访问者结构复杂且限制苛刻,解释器则是公认几乎用不到的一个。把它们放一起,不是敷衍,而是要传递一个和全系列一脉相承的态度:这三个模式,你更需要知道的是它们解决什么问题、以及为什么大多数时候你不该用它们,而不是把它们的模板背下来到处套。所以这一篇的写法和前面不同:每个模式我只讲清三件事——它解决什么问题、核心怎么做、以及为什么适用面这么窄,点到为止,不铺长。读完你能认出它们、知道它们的定位,并在极少数真正需要的场景里想起它们,就够了。目录中介者:让一群对象别再两两纠缠访问者:数据结构稳定,操作却不断加解释器:为一种小语言定义文法三个模式的共同点:适用面都很窄一、中介者:让一群对象别再两两纠缠中介者模式解决什么问题?当一堆对象之间两两直接通信、相互引用时,它们会织成一张乱麻般的网——每个对象都要认识一大堆别的对象,任何一个改动都可能牵连一片。中介者的思路:引入一个中介者对象,让所有对象都只跟中介者通信,而不再彼此直接引用,把网状的多对多关系,变成星型的一对多。一个订单场景的例子:下单页的组件联动。下单页上有一堆相互关联的组件:选了优惠券,总金额要变;改了收货地址,运费要变,运费变了总金额又要变;改了商品数量,金额、运费、优惠资格全要重算……如果每个组件都直接持有并调用其他组件,就是一张可怕的网。用中介者,让每个组件的变化都通知下单页中介者,由中介者统一协调这个变了、该让哪些组件跟着更新:// 中介者:统一协调各组件的联动publicclassOrderPageMediator{privateCouponComponentcoupon;privateAddressComponentaddress;privateAmountComponentamount;// ... 持有各组件// 某个组件变了,通知中介者,由它决定联动谁publicvoidchanged(Componentsource){if(sourcecoupon){amount.recalculate();}if(sourceaddress){amount.recalculate();/* 还有运费等 */}// 协调逻辑集中在这里}}// 组件不再直接调别的组件,只通知中介者publicclassCouponComponent{privateOrderPageMediatormediator;publicvoidselect(){// ... 选优惠券mediator.changed(this);// 只告诉中介者我变了,不管谁联动}}好处很清楚:组件之间彻底解耦了,每个组件只认识中介者,不认识其他组件;所有的联动规则集中在中介者一处,清晰可查;加一个新组件,只需让它接入中介者。这和第 11 篇的外观模式有点像(都是加一个中间层),但意图不同:外观是单向的(简化外部对子系统的调用),中介者是双向的(协调内部一群对等对象的相互通信)。为什么它适用面窄、还容易被滥用?最大的风险是——中介者本身会膨胀成一个上帝类。因为所有协调逻辑都往中介者里塞,组件越多、联动越复杂,中介者就越臃肿,最后变成一个几百上千行、什么都管、谁都不敢碰的巨无霸。你只是把分散在各处的耦合,转移成了高度集中在一个类里的复杂度。所以中介者的适用场景很挑:只有当对象间确实是多对多的复杂交互、且交互逻辑适合集中管理时才用;如果对象关系本来就简单、或只是单向依赖,用它纯属自找麻烦。现实里 GUI 框架的表单联动、聊天室(用户通过服务器中转消息,而非两两直连)是它比较合适的场景。二、访问者:数据结构稳定,操作却不断加访问者模式解决什么问题?当你有一个稳定的数据结构(元素的种类基本固定),但需要不断给它增加新的操作时,访问者能让你在不修改元素类的前提下,新增操作。它的核心手法有点绕:把操作从元素类里抽出来,封装成一个个独立的访问者;元素只提供一个accept(visitor)方法,把自己交给访问者去处理。一个订单场景的例子:对订单集合做多种统计/导出操作。假设订单里有不同类型的元素(实物商品、虚拟商品、服务),你需要对它们做各种操作:算总价、导出 Excel、生成报表、统计重量……而且这些操作会不断新增。如果把每个操作都写进元素类,那每加一个操作,所有元素类都要改。访问者反过来:// 访问者接口:为每种元素类型定义一个 visit 方法publicinterfaceOrderVisitor{voidvisit(PhysicalItemitem);voidvisit(VirtualItemitem);}// 每个操作是一个访问者publicclassPriceVisitorimplementsOrderVisitor{voidvisit(PhysicalItemitem){/* 算实物价 */}voidvisit(VirtualItemitem){/* 算虚拟价 */}}publicclassExportVisitorimplementsOrderVisitor{/* 导出逻辑 */}// 元素只提供 accept,把自己交给访问者publicclassPhysicalItemimplementsItem{publicvoidaccept(OrderVisitorvisitor){visitor.visit(this);}}于是新增一个操作(比如统计重量),只需写一个新的WeightVisitor,所有元素类一个字都不用改。这就是访问者的价值——把操作这个变化维度,从元素类里彻底解放出来。为什么它适用面极窄?因为它有一个致命的倾斜性(和第 4 篇抽象工厂的倾斜性异曲同工):它对增加操作友好,但对增加元素类型极其敌视。新增一个操作 → 加一个访问者,爽;但新增一种元素类型(比如加个ServiceItem)→ 你得回去修改每一个访问者接口和所有实现,加上对新元素的visit方法——牵一发动全身,彻底违反开闭。所以访问者的适用前提非常苛刻:元素种类必须高度稳定(几乎不变),而操作会频繁增加。满足这个前提的场景本就不多(编译器的 AST 处理是经典例子:语法树节点类型固定,但要对它做类型检查、代码生成、优化等很多种操作)。加上它那套accept/visit的双分派结构本身就绕、可读性差,所以业务开发里极少用到。看到它能认出、知道它解决稳定结构 多变操作即可。三、解释器:为一种小语言定义文法解释器模式解决什么问题?当你需要处理一种简单的、自定义的小语言(比如一套规则表达式、一种查询语法)时,解释器提供一种方式:为这个语言定义一套文法,把每条文法规则表示成一个类,然后用这些类的对象组成一棵语法树,通过遍历这棵树来解释执行表达式。一个订单场景的例子:优惠规则表达式。假设运营想灵活配置优惠规则,比如金额100 AND 会员这样的表达式。解释器会把它拆成一棵树:AND是一个节点,左边是金额100(一个表达式),右边是会员(一个表达式),每种表达式是一个实现了interpret()的类,递归地解释求值:publicinterfaceExpression{booleaninterpret(Contextctx);// 解释:在给定上下文下求值}// 与 表达式publicclassAndExpressionimplementsExpression{privateExpressionleft,right;publicbooleaninterpret(Contextctx){returnleft.interpret(ctx)right.interpret(ctx);// 递归解释子表达式}}// 金额大于 表达式、是会员 表达式 ... 各是一个类你会发现,它的结构本质上就是第 10 篇组合模式(树形结构 递归)——解释器可以看作组合模式在’语言解释’这个特定场景的应用。为什么它几乎用不到?三个原因:其一,适用面极其狭窄——只有需要解释一种自定义小语言这一种场景才用得上,而这种需求本就罕见。其二,类爆炸——文法规则稍微一多,就要定义一大堆表达式类,复杂文法下根本维护不了。其三,有更好的替代——真要处理复杂表达式/语言,现实中都用成熟的工具:正则表达式、脚本引擎(如 Groovy、JS 引擎)、规则引擎(如 Drools)、或专门的解析器生成器(ANTLR),它们比手写解释器强大和健壮得多。所以解释器是二十三式里公认最少用的一个。它的价值更多是思想启发(理解语言是怎么被解析执行的),而非实战工具。了解它是什么、知道真要做这事有更好的轮子,就足够了。四、三个模式的共同点:适用面都很窄把这三个模式放一起收个尾,它们其实共享一个特征,也正是我们合并讲的原因:适用场景都非常窄,且都有明显的反噬风险。模式解决什么为什么少用中介者多对多交互 → 集中协调中介者易膨胀成上帝类访问者稳定结构 多变操作加元素类型就牵一发动全身;结构绕解释器解释自定义小语言场景罕见 类爆炸 有更好的轮子这三个模式,恰恰是全系列别过度设计这条主线最好的注脚。它们不是高级“厉害的模式,恰恰相反,它们是最需要克制的模式——因为它们结构复杂、限制苛刻,一旦用错场景,带来的复杂度远超收益。真正成熟的做法,不是我学会了访问者所以要找机会用”,而是我知道访问者的存在,但我清楚我这个场景的元素类型还会变,所以我不用它。知道一个模式什么时候不该用,和知道它怎么用,同等重要——甚至更重要。用一张图把这三个冷门模式的定位和别用它的信号钉在一起:小结。这一篇把行为型里最冷门的三个模式集中讲了:中介者用一个中介者集中协调一群对象的多对多交互,把网状耦合变星型,但要警惕它膨胀成上帝类;访问者把操作从稳定的数据结构里抽出来、以便不改元素就新增操作,但它对新增元素类型极度敌视、结构也绕,业务里极少用;解释器为一种自定义小语言建语法树来解释执行,但场景罕见、易类爆炸、且有正则/脚本引擎/规则引擎等更好的替代,是最少用的一个。它们共同的教训呼应全系列的主线——这些模式最需要的是克制,知道什么时候不该用它们,比会用更重要。下一篇是整个「设计模式拆解」系列的收尾总纲:我们会盘点 JDK/Spring/MyBatis 源码里的模式、集中辨析那些容易混淆的成对模式、再谈一次过度设计,把二十三个模式和七大原则串成一张完整的地图。

相关新闻

先进过程控制(APC)在半导体良率提升中的核心作用与实践指南

先进过程控制(APC)在半导体良率提升中的核心作用与实践指南

1. 项目概述:当良率遇到瓶颈,我们该看向哪里?在晶圆制造的漫长链条里,良率(Yield)是最终决定一切商业成败的“圣杯”。产线上的工程师们每天都在和光刻对准、薄膜厚度、刻蚀均匀性这些具体的工艺参数搏斗&a…

2026/8/13 1:32:56 阅读更多 →
3分钟上手:B站视频下载神器BiliDownloader全面指南

3分钟上手:B站视频下载神器BiliDownloader全面指南

3分钟上手:B站视频下载神器BiliDownloader全面指南 【免费下载链接】BiliDownloader BiliDownloader是一款界面精简,操作简单且高速下载的b站下载器 项目地址: https://gitcode.com/gh_mirrors/bi/BiliDownloader 还在为无法保存喜欢的B站视频而烦…

2026/8/13 1:32:56 阅读更多 →
基于SpringBoot的智能物业管理系统设计与实现

基于SpringBoot的智能物业管理系统设计与实现

1. 项目概述小区物业管理系统是现代社区管理的重要工具,它通过信息化手段整合物业资源、提升服务效率。基于Java和SpringBoot的智能化物业管理系统,能够实现业主信息管理、物业费收缴、报修处理、设备维护等核心功能,同时支持移动端访问&…

2026/8/13 1:32:56 阅读更多 →

最新新闻

19 — 贮藏与清理:stash 是抽屉,gc 是打包箱

19 — 贮藏与清理:stash 是抽屉,gc 是打包箱

19 — 贮藏与清理:stash 是抽屉,gc 是打包箱 摘要: 本章介绍 Git 中两个实用工具:git stash 用于临时贮藏未提交的改动(像把桌面物品扫进抽屉),方便切换分支处理紧急任务;git gc 用…

2026/8/13 12:49:58 阅读更多 →
Docker Compose从入门到精通:多容器应用编排实战指南

Docker Compose从入门到精通:多容器应用编排实战指南

1. 项目概述:为什么需要Docker Compose? 如果你已经接触过Docker,大概率经历过这样的场景:为了跑起一个稍微复杂点的应用,比如一个带数据库、缓存和Web服务的项目,你需要在终端里敲下一连串的 docker run …

2026/8/13 12:49:57 阅读更多 →
开源M3U8下载器:多线程加速800%,支持API与批量处理

开源M3U8下载器:多线程加速800%,支持API与批量处理

这次我们来看一个能极大提升 M3U8 视频下载效率的开源工具。对于经常需要处理在线视频素材的开发者、内容创作者或技术爱好者来说,M3U8 格式的流媒体文件下载一直是个痛点:速度慢、容易中断、不支持批量操作。这个项目直接瞄准了这些痛点,通过…

2026/8/13 12:49:57 阅读更多 →
CUDA 10.1与cuDNN安装配置全攻略:从原理到实践,避坑指南与深度学习环境搭建

CUDA 10.1与cuDNN安装配置全攻略:从原理到实践,避坑指南与深度学习环境搭建

1. 项目概述:为什么CUDA与cuDNN的安装如此关键? 如果你正在踏入深度学习、高性能计算或者计算机视觉的领域,那么“CUDA”和“cuDNN”这两个词对你来说,绝对不陌生。它们就像是开启NVIDIA GPU全部潜力的两把钥匙。CUDA是NVIDIA推出…

2026/8/13 12:49:57 阅读更多 →
HiveWE 地图编辑器:把加载从5分钟砍到5秒,一个周末做出一张能玩的魔兽地图

HiveWE 地图编辑器:把加载从5分钟砍到5秒,一个周末做出一张能玩的魔兽地图

HiveWE 地图编辑器:把加载从5分钟砍到5秒,一个周末做出一张能玩的魔兽地图 【免费下载链接】HiveWE A Warcraft III world editor. 项目地址: https://gitcode.com/gh_mirrors/hi/HiveWE 深夜十一点,我对着原版地图编辑器那条卡到一半…

2026/8/13 12:49:57 阅读更多 →
Postman自动化Token管理:从JWT获取到接口测试全流程实战

Postman自动化Token管理:从JWT获取到接口测试全流程实战

1. 项目概述:为什么我们需要在Postman里搞定Token? 做接口测试或者前后端联调,如果你还在手动复制粘贴那一长串看起来像乱码的Token,那效率可就太低了。Token,无论是简单的API Key,还是复杂的JWT&#xff0…

2026/8/13 12:48:57 阅读更多 →

日新闻

Visual Studio新建项目解决方案为空:系统性排查与修复指南

Visual Studio新建项目解决方案为空:系统性排查与修复指南

1. 问题现象与本质剖析如果你是一位.NET开发者,或者正准备踏入这个领域,那么Visual Studio(后面简称VS)绝对是你绕不开的伙伴。但有时候,这个伙伴会跟你开一个不大不小的玩笑:你满怀期待地点击“创建新项目…

2026/8/13 0:00:09 阅读更多 →
长春建设厅网站:普通人买房办事必看的真实指南与避坑攻略

长春建设厅网站:普通人买房办事必看的真实指南与避坑攻略

说实话,每次提起“长春建设厅网站”这几个字,我心里都挺有感触的。不是因为它有多高大上,也不是因为那里藏着什么不可告人的秘密,恰恰相反,是因为它太“接地气”了,或者说,它是咱们普通人想要在这个城市好好生活、安稳买房时,必须得翻过的一座“数据山”。很多新朋友第…

2026/8/13 0:00:09 阅读更多 →
Windows家庭版远程桌面多用户破解完整指南:RDPWrap终极解决方案

Windows家庭版远程桌面多用户破解完整指南:RDPWrap终极解决方案

Windows家庭版远程桌面多用户破解完整指南:RDPWrap终极解决方案 【免费下载链接】rdpwrap.ini RDPWrap.ini for RDP Wrapper Library by StasM 项目地址: https://gitcode.com/GitHub_Trending/rd/rdpwrap.ini 你是否曾为Windows家庭版无法支持多用户远程桌面…

2026/8/13 0:00:09 阅读更多 →

周新闻

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁 【免费下载链接】baidupankey 在线查询网盘提取码(维护中 rm repo) 项目地址: https://gitcode.com/gh_mirrors/ba/baidupankey 你是否曾经在深夜寻找一份重要资料&#x…

2026/8/13 2:38:34 阅读更多 →
如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南 【免费下载链接】chinese_license_plate_generator 中国车牌生成器 项目地址: https://gitcode.com/gh_mirrors/ch/chinese_license_plate_generator 中国车牌生成器是一个基于Python的开源项目&#xff0c…

2026/8/13 10:41:52 阅读更多 →
收藏!小白程序员轻松入门大模型,从Harness工程开始实践

收藏!小白程序员轻松入门大模型,从Harness工程开始实践

文章强调学习大模型不应只关注模型本身,而应重视模型外的系统搭建,即Harness。提出AgentModelHarness的实用公式,详细介绍Harness的四个层次:持久化层、执行层、控制层和观察与验证层。文章还探讨了上下文工程、工具设计、AGENTS.…

2026/8/13 10:41:51 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/13 10:41:50 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/13 10:41:49 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/13 10:41:49 阅读更多 →