大家都知道23种设计模式。但从面试和业务落地的角度看:
- 首先,根本用不上这么多的设计模式。
- 其次,设计模式根本不是一门“背术语”的学科,它真正考的是:当代码开始变复杂时,你有没有能力把变化点隔离出来,把耦合拆开,把扩展性留出来。
设计模式这章,真正的结论其实很简单:不是先学会模式再写代码,而是先遇到变化和复杂度,再知道该用哪种模式去消化它。
首先,设计模式不是为了炫技,而是为了处理高频的软件设计问题。它解决的核心矛盾,永远是变化和复杂度。
在创建对象这条线上,最重要的是:
- 单例解决“全局唯一”
- 工厂解决“创建逻辑解耦”
在组织类关系这条线上,最重要的是:
- 代理解决“控制访问”
- 装饰器解决“动态增强”
- 适配器解决“接口兼容”
在组织行为流程这条线上,最重要的是:
- 策略解决“算法可替换”
- 模板方法解决“流程骨架固定,局部步骤可变”
- 观察者解决“一变多通知”
- 责任链解决“请求沿链路逐步处理”
这一切的底层思想,最后都能回到开闭原则、依赖倒置、里氏替换这些面向对象设计原则上。
所以设计模式这章,主线其实是:
- 为什么需要设计模式?
- 创建对象时常见的问题怎么解?
- 组织类关系时常见的问题怎么解?
- 组织行为流程时常见的问题怎么解?
为什么需要模式?
设计模式本质上不是“高级写法”,而是前人总结出来的一套高频设计问题的通用解法。
当系统开始变大时,我们最常遇到的几个问题其实非常朴素:
- 对象创建逻辑越来越复杂;
- if-else 越来越多;
- 一个类承担了太多职责;
- 业务变种越来越多,改一处牵一片;
- 新需求不是加功能,而是和旧功能交错着长。
所以设计模式的价值,从来不是“代码看起来高级”,而是:
- 降低耦合
- 提高可扩展性
- 隔离变化点
- 让复杂系统更容易演化
相关阅读:
设计模式真正学到最后,离不开三条底层原则:
- 开闭原则:对扩展开放,对修改关闭。
- 依赖倒置:依赖抽象,不依赖具体实现。
- 里氏替换:子类必须能替换父类而不破坏原有语义。
这些原则不是单独考的理论,它们其实就是后面所有模式的底层哲学。
相关阅读:
对象到底该怎么创建
很多系统一开始写得很简单,直接 new 就完了。但当对象创建过程开始变复杂,比如:
- 初始化步骤很多;
- 不同环境要创建不同实现;
- 某些对象必须全局唯一;
- 一组产品要成套出现;
这时候直接 new 就不够用了。这个时候就引入了第一类设计模式了。
单例模式
单例的核心不是“语法写法”,而是回答一句话:这个对象是不是全局只需要一个?
典型场景包括:
- 配置中心对象
- 线程池管理器
- 缓存管理器
- 某些全局协调组件
相关阅读:
工厂模式
工厂模式本质上解决的是:对象创建逻辑不要散落在业务代码里。 你可以把它理解成“把 new 的复杂性封装起来”。
- 简单工厂:一个工厂类根据条件返回不同产品。
- 工厂方法:把“生产什么”这件事下放到不同工厂子类。
- 抽象工厂:生产一整套相互关联的产品族。
所以这三者不是“谁更高级”,而是应对复杂度的层级不一样。
相关阅读:
建造者模式
把复杂对象的「构建过程」和「内部表示」拆开,不用写一堆重载构造方法,链式调用优雅创建对象。
适用场景:对象属性特别多、创建步骤繁琐、参数组合灵活、不想写重叠重载构造器。比如:
- 复杂实体(用户、订单参数很多字段)
- 配置类、请求参数类
- 创建过程固定,但内部部件可以自由组合
类关系怎么组织更灵活
当系统复杂之后,第二类问题往往不是“怎么创建对象”,而是“怎么在不改原始类的情况下扩功能”。
代理模式
代理模式的核心是:我不直接访问目标对象,而是通过一个中间层控制访问。
这类模式特别适合做:
- 权限校验
- 延迟加载
- 远程调用封装
- 事务、日志、监控增强
Spring AOP、RPC 框架代理、本地缓存代理,本质上都能往这一类里靠。
而且代理模式还可以顺便把静态代理和动态代理串起来:静态代理更直白,但容易类爆炸;动态代理更灵活,更适合框架化能力。
相关阅读:
- 代理模式和装饰器模式有什么区别?静态代理和动态代理分别适合什么场景?
装饰器模式
装饰器模式和代理模式长得很像,所以特别容易混。
它们的共同点是都会包一层对象、都可能实现相同接口;但核心区别在于目的,代理更偏控制访问、装饰器更偏动态叠加功能。
最经典的思路是:原始对象不改,通过一层层装饰把额外能力套上去。Java IO 那一大串 InputStream / BufferedInputStream / DataInputStream,就是特别标准的装饰器思路。
相关阅读:
适配器模式
适配器模式本质上解决的是接口不兼容。适配器不是为了增强功能,而是为了让两个原本对不上的接口接上。
当老系统有一套接口,新系统期待另一套接口,但你又不想改原始实现,这时候就可以做一层适配,把原有能力“翻译”成新接口能听懂的样子。
一段业务流程怎么设计得更可扩展
很多真实业务里,最麻烦的问题其实不是建模,而是行为流程越来越复杂。
比如:支付方式越来越多、审批规则越来越多、活动规则越来越多、同样一条主流程里,局部步骤会随场景变化。
这一类问题,最常见会落到策略、模板方法、观察者、责任链。
策略模式
策略模式特别适合解决:同一件事情有多种算法或处理方式,而且它们可以互相替换。
最典型场景:不同支付方式、不同优惠计算方式、不同路由规则、不同排序/过滤算法
它的核心思想是把算法抽出来,业务上下文只依赖抽象策略,不写一长串 if-else。
相关阅读:
模板方法模式
模板方法和策略经常一起考,因为它们都在解决“流程变化”问题。区别在于:
- 策略模式是把整块算法外置,运行时替换。
- 模板方法是把主流程固定住,只把某些步骤留给子类定制。
也就是说,模板方法更像“骨架稳定、局部可变”的模式。
比如一套标准下单流程、标准消息发送流程、标准风控流程,主干步骤不变,但某几步根据渠道不同可以覆写。
观察者模式
观察者模式特别适合“一变多通知”的场景。当一个对象状态变化时,需要通知很多依赖方,比如:
- 订单状态变化通知积分、库存、消息模块
- 配置变化通知多个监听器
- 领域事件触发多个后续动作
这里最关键的理解是:观察者模式本质上是在做解耦通知。
而它和发布订阅的区别,往往在于中间是否引入事件总线/消息代理。观察者通常更偏进程内直接订阅关系,发布订阅更容易进一步扩展成分布式消息模型。
相关阅读:
责任链模式
责任链模式特别适合:请求需要经过一串处理器,但到底谁处理、处理到哪一步,不希望在入口处写死。Spring MVC 的拦截器链、Servlet Filter 链,都是特别经典的责任链思想。
典型场景包括:过滤器链、拦截器链、审批流、风控规则链
它的核心是把处理节点串起来,让请求沿链条逐步传递。
- 优点很明显:扩展处理节点很方便;符合开闭原则;把复杂判断拆散了;
- 但也有缺点:链路太长时不好排查;顺序依赖会变重。
相关阅读: