这里不写模式的定义。两个问题值得回答:模式当初补的表达力缺口,如今由谁承担;留下来的模式要付出什么代价。

二十六篇文章,每篇一个模式,实验都在同一台机器(Apple M1 Pro)上跑两遍:JDK 21.0.8 与 JDK 25,源码引用逐字取自 JDK 25 的 src.zip。测量方法与局限写在每篇里,结论只建立在量级上。

总纲

文章 回答的问题
设计模式——被语言吃掉的那些模式 哪些 GoF 模式已被语言特性取代、哪些还留着,判据是哪三条

创建型

文章 回答的问题
设计模式——单例的五种写法与代价 五种写法各自把成本花在哪,哪种写法挡得住哪几种破坏
设计模式——建造者模式(Builder pattern) 参与者有哪些,JDK 源码与 Lombok 各自怎么落地
设计模式——工厂方法:创建动作的成本 直接 new、Supplier、反射构造、方法句柄四条创建路的耗时与分配,以及反射 inflation 的一手验证
设计模式——抽象工厂:产品族的一致性 换一套实现的代价,以及族约束由编译器还是运行期兜底
设计模式——原型:拷贝的四条路 clone、拷贝构造、深拷贝、序列化四者的耗时与分配差到几百倍,哪条路是浅拷贝

结构型

文章 回答的问题
设计模式——装饰器:缓冲链的代价 多包一层换来什么,缓冲层放错位置会怎样,flush 语义为什么不统一
设计模式——代理:动态代理的成本与边界 生成的代理类长什么样、缓存在哪、每次调用的分配从哪来、this 调用为什么绕开拦截
设计模式——适配器:边界在哪 适配层被内联之后成本测不出来,多实现调用点为什么让它重新出现
设计模式——桥接:两个维度独立变化 m×n 的类爆炸值多少字节、多少类加载时间,多一层间接分派贵多少
设计模式——组合:树与叶子的同一接口 递归遍历与先展平的交叉点,栈深临界值,类型抹平的代价
设计模式——外观:批量接口的价值 细粒度调用收成批量之后 syscall 次数与耗时各降多少,Files.write 自带几层缓冲
设计模式——享元:共享不可变状态 JDK 把缓存边界写在哪,-XX:AutoBoxCacheMax 改的是什么

行为型

文章 回答的问题
设计模式——责任链:三种形态 日志 Handler 链、Stream stage 链、HttpClient 过滤器链的成本曲线与短路位置的影响
设计模式——观察者:从 Observable 到背压 推模式缺的为什么是流量控制,SubmissionPublisher 缓冲写满时 submit 阻塞多久
设计模式——状态:状态位还是状态类 JDK 用位标志加 CAS 管状态,状态类写法慢在哪,非法迁移的三种兜底值多少
设计模式——策略:有状态与无状态 策略有没有状态,成本落在调用上还是分配上
设计模式——命令:撤销栈与队列化 把调用变成对象之后买到什么、付多少,快照与反向操作两条撤销路的内存差
设计模式——解释器:解释还是编译 语法树求值与编译成闭包为什么打平,Pattern.compile 每次编译贵在哪
设计模式——中介者:谁负责协调 N² 引用换成 N 的收益,以及中介者自己变成热点之后多线程吞吐掉多少
设计模式——备忘录:快照的代价 全量快照、增量日志、写时拷贝三条路的快照耗时、常驻内存与回滚耗时
设计模式——迭代器:分配与逃逸分析 迭代器分配什么时候被标量替换掉,什么时候逃逸成真实分配
设计模式——访问者:类型与操作的矩阵 类型轴与操作轴哪一边先长,两个扩展方向各改多少文件,每次分派差多少纳秒
设计模式——模板方法:钩子的成本 空钩子的数量什么时候开始花钱,默认实现里的逐字节退化

不在 GoF 里,但算同一类问题

文章 回答的问题
设计模式——对象池:什么时候是负优化 分配成本与同步成本的交叉点在几个线程,什么对象才值得池化
设计模式——不可变与防御性拷贝 共享与拷贝这两笔账怎么算,List.copyOfunmodifiableList 差在哪

与 Java 系列的关系

模式是语言表达力的补丁,判断一个模式还要不要用,得先看今天的语法给到了什么。这条线与 Java 系列 共用同一批实测环境,语言特性那一组文章是本文集的前置阅读。

阅读建议

先看总纲,那篇给出判据并附三组对照实验,其余二十五篇都在它划出的框架里展开。想找具体问题的答案就直接翻对应那篇:每篇开头是问题与结论,中间是实验设计和原始数据,结尾是判断顺序。