EnriqueMark
设计模式与架构

绞杀榕模式

2026-04 简体中文

Strangler Fig 是一种寄生植物,会逐渐缠绕并吸取宿主的营养,最终让宿主枯萎,自己蓬勃生长取而代之,谓之「绞杀」。因此,绞杀榕模式的核心也可以用一句话概括:「逐步生长,逐步接管,逐步替换,逐步移除。」

这是一个蛮有意思的设计模式,面向的核心场景是旧业务老旧、重构困难尾大不掉,而又想引入新的现代化技术时,就会采用这个模式。其核心关键是最大化兼容和隔离,保证新功能的边界严格控制在新功能処,而对外暴露的是兼容的旧接口。旧系统将在可预期的时间内和新系统长期共存,直到新系统彻底且安全的取代了所有旧系统实现的功能。

比起彻底推导老旧系统的大爆炸重写(Big Bang Rewrite),逐步且渐进的替代显然更加安全和低成本。和这个设计模式搭配的一般都是微服务,将旧系统隔离在一个代理层后,此前一切照旧,此后一切从新。出现问题时代理层也会成为风险隔离的护盾,而不至于牵一发动全身,导致重构不成,旧功能也全面失效。放在前端则是以孤岛模式为主的微前端——本质上是彻底模块化的容器思想。因为本身就没什么耦合,也能做到最小化影响。它天然的模块化设计架构,也让测试非常方便。内外不耦合,输入输出明确,测起来也很轻松。

前端重构的流程就可以是这样:对旧项目以微前端的形式逐步引入单一的新功能模块,内部完全采用Angular或者React这种现代化框架构建。同时,保证其最终的编译产物和调用可以在整体的旧系统下兼容。对旧的系统来说,它不会看到这里出现了「新东西」,而是「一切照常」(就跟被寄生的宿主感觉不到一样,但实际已经在流失营养)。核心的关键关键是保证整体的迁移过程的可靠性和可控性,控制问题在限定范围内,做好随时回退的便捷入口,最好是一键卸载。

其次,不能光顾著功能上隔离,也要保证数据上的隔离。在数据处理上需要设置一个防腐层,以免旧数据结构污染到新模块,导致严重的隐性数据依赖问题。比如某个依赖于旧功能的特殊字段,如果新模块直接取,那未来移除旧模块后这里就会直接炸。

特别就前端来说,CSS上的隔离也至关重要。这个不只是旧系统的全局样式会污染新系统的样式,还有反过来的,比如Tailwind CSS这种UI库就可能存在CSS Reset,一旦我把它挂到旧系统的接口除,那就可能导致其顺著整个管线上去把旧系统的样式也全改了。所以这算是一个需要考虑的边界问题。

不过,若是旧业务的部分内容耦合严重,有大量状态依赖,那就不适合强行往里面塞新架构。能做到边界清晰永远是替换的前提,双方只用契约结构进行交流。新的部分不应该大量和旧页面共享状态,否则旧的一拆,新的就全完。