算法和设计模式常被放在面试语境里,但在工程里,它们真正解决的是两个问题:数据规模变大后成本怎么增长,代码变化变多后职责怎么安排。
复杂度先帮你判断量级
时间复杂度描述输入规模变大时,执行时间如何增长。O(1) 是常量级,O(n) 是线性增长,O(n²) 常见于双层循环,O(n log n) 常见于高效排序。
复杂度不是唯一指标。实际工程还要看数据规模、I/O、缓存命中、对象分配和实现成本。一个 O(n) 的简单遍历,在几千条数据上可能比复杂索引方案更稳定;但在千万级数据上,错误的复杂度会迅速变成事故。
排序算法要看稳定性和数据特征
插入排序、选择排序、快速排序、归并排序、堆排序,各自关注点不同。
插入排序在小规模或基本有序数据上很实用;选择排序交换少但不稳定;归并排序稳定但需要额外空间;快速排序平均性能好,但最坏情况会退化;堆排序空间友好,但实现和局部性不一定占优。
工程里不一定要手写排序,但理解这些差异有助于判断库函数、数据库排序和内存排序的成本边界。
一致性哈希解决扩缩容抖动
简单取模 hash(key) % n 在节点数量变化时会让大量 key 重新映射。节点从 3 台变 4 台,原来的命中关系会大面积失效,缓存系统可能瞬间把压力打回数据库。
一致性哈希把节点和 key 都映射到一个环上,key 顺时针找到最近节点。新增节点只影响相邻区间,删除节点也只把局部数据迁移到下一个节点。
虚拟节点可以让负载更均匀。每台物理机对应多个虚拟节点,扩容时从多个老节点分摊流量,避免新节点只接管一小段或一大段。
设计模式是职责组织方式
创建型模式关注对象如何创建,结构型模式关注对象如何组合,行为型模式关注对象之间如何协作。
常见例子很贴近 Java 工程:
- 工厂和建造者用于封装复杂创建过程。
- 适配器用于兼容旧接口或第三方 SDK。
- 装饰器用于在不改原对象的情况下增强能力。
- 代理常见于 AOP、RPC 和权限控制。
- 策略用于替换大段
if/else分支。 - 责任链常见于 Filter、拦截器和审批流。
模式不是为了显得高级,而是为了把变化点放到合适的位置。
不要为了模式牺牲可读性
设计模式有边界。一个简单业务只有两三个分支,直接写清楚可能比硬上策略模式更好。一个对象创建过程并不复杂,也不需要建造者。
判断是否需要模式,可以看三点:
- 变化点是否已经出现,还是只是假想未来会变。
- 抽象后调用方是否更容易理解。
- 新增能力时是否真的减少修改范围。
如果答案都是否定的,就先保持简单。
实用结论
算法帮助你理解规模成本,设计模式帮助你组织变化。前者让系统在数据变大时不失控,后者让代码在需求变多时不混乱。
工程里最好的使用方式不是背名词,而是在具体问题里判断:数据量会不会变大,节点会不会扩缩容,职责会不会变化,抽象是否真的降低维护成本。




