翻开一段代码,所有类名、方法名都认识,每一行都能读懂。但合在一起不知道在干什么。
换一个场景:需要加一个新功能,改了接口之后,五个实现类全部报错。不是代码写得烂,是依赖关系长成了蜘蛛网,没人画过结构图。
设计模式要解决的就是这种困境。它不是"更优雅的写法",是一套让代码结构的意图变得可见的语言。
看懂结构图比背模式名更重要
GoF 的 23 个设计模式,背名字和分类不难。Strategy、Observer、Factory——面试能答出来不代表在实际代码里认得出来。
图解的价值在这里。一张类图把角色、职责和消息流向画清楚,你看到的不再是"这个模式叫什么",而是"这段代码的对象之间是什么关系"。
比如看到一个类的方法里全是 if-else 分支,每个分支做类似但不同的事情——画成图就是 Strategy 的候选场景。不是因为"应该用 Strategy",而是图上能看出行为被硬编码在控制流里了。
模式解决的是变更方向上的问题
设计模式不是让代码更短或更快。它解决的是一个非常具体的问题:当需求沿某个方向变化时,改动的范围能不能控制住。
Observer 解决的是"一个状态变了,多个地方要响应"。如果响应方的数量是固定的,直接写死也没问题。但如果响应方会增减,没有 Observer 的结构就意味着每次增减都要改通知方的代码。
Decorator 解决的是"功能要叠加但叠加顺序不确定"。如果组合方式是固定的,一个函数搞定。但如果需要运行时组合,硬编码的层叠结构就会爆炸。
每个模式都有自己"最有效的变更方向"。用对了是杠杆,用错了是多余的抽象层。
图纸能传递意图,代码未必能
一段使用了 Template Method 的代码,如果不画图、不写注释,后来的人看到的是"一个抽象类调了几个虚方法"。他可能会直接改抽象类里的逻辑,破坏了"算法骨架不变,步骤可替换"的设计意图。
类图和时序图的作用就是把这层意图显式化。它告诉后来的读者:这段代码故意这样组织,不是因为写的人不会简单写法,而是因为这里的变化方向需要这种结构来承接。
在团队协作中,图的沟通效率比代码高一个数量级。三个人对着代码讨论半小时没达成共识的事情,画一张图五分钟就清楚了。
不是所有重复都需要模式
看到重复代码的第一反应是"要不要引个模式消除掉"。多数时候,答案是不需要。
两处代码长得像但变更方向不同,强行统一反而制造耦合。三段 if-else 现在觉得丑,但如果分支不会再增加,引入 Strategy 就是过度设计。
判断要不要用模式的关键问题只有一个:这个位置未来最可能沿哪个方向变化?如果答案清晰,对应的模式就浮现了。如果答案不清晰,暂时不引入是最安全的选择。