策略模式实战:从开户代码到设计模式的代价
这是一篇给自己备的讲课稿,也是一个真实的代码故事:同样一块「开户」业务,正着写是设计模式,反着写是
if+ 复制粘贴。借这个例子,顺手把策略模式讲清楚,也把它的代价讲清楚。
开场:为什么拿开户举例子
一会儿讲设计模式,我想用一个自己真实做过的例子——开户。
最开始我是负责微结构开户这块代码的。开户这件事,其实不只是「新建一个客户」这么简单。我刚上手的时候,脑子里就已经在想整条链路了:
- 开户、过户、销户,是一整套生命周期;
- 开户过程里会碰到的不同用户类型——居民客户、企业客户、商业客户、虚拟客户等等;
不同类型,后面走的流程是不一样的。
当时我就想到了策略模式。
策略模式,说白了是什么
策略模式其实不玄。说白了就是一句话:给不同的人,用不同的套路。
你可以把它想象成销冠卖货。销冠不会对所有人说同一套话——遇到什么人讲什么话,遇到难缠的人要更有耐心。他自己会沉淀一套稿子,甚至能传给其他销售。
这套「见人说人话」的准备,就是套路。
策略模式跟这个特别像。策略,就是套路。
开户里怎么用
开户也是一样。人进来了,先判断他是什么人:居民、企业、商业、虚拟……
大流程其实都差不多:校验 → 走业务 → 后置处理。骨架是一套,细节不一样。
所以我当时就用策略模式做了一层简单封装:
- 公共流程固定:校验、业务、后置,谁都走这一套;
- 差异点下沉到不同策略:居民一套、企业一套、商业一套、虚拟一套。
示意一下骨架(伪代码,不绑定具体语言):
接口 OpenAccountStrategy {
校验()
执行业务()
后置处理()
}
居民策略 implements OpenAccountStrategy { ... }
企业策略 implements OpenAccountStrategy { ... }
商业策略 implements OpenAccountStrategy { ... }
虚拟策略 implements OpenAccountStrategy { ... }
主流程(context):
策略 = 根据客户类型选择(策略表)
策略.校验()
策略.执行业务()
策略.后置处理()
这样一来,后面要加新的客户类型,理想情况下是新增一个策略类,而不是在一个大方法里继续堆 if-else。
反例:后来发生了什么
后面我有点无奈。
因为我太忙了,又被拉去做订单支付,开户这块就交给了另一个后端。他做得确实不是很好。
他怎么做的呢?把我的代码直接复制一份,前面加个 if,走进他自己的代码块;还让前端加一个字段来区分。
if (是新人负责的某种客户) {
// 复制出来的实现,粘贴在这里
} else {
原来的策略流程
}
这就是一个很经典的反例:他没看懂策略模式,所以只能用最直接的方式把事情做完。代码能跑,业务也能交差,但设计和扩展性基本没了。
注意,我不是说他态度不好。很多时候就是:他写代码,只是为了完成这件事。
顺势讲设计模式的缺点
这就正好走到设计模式的一个缺点:对开发人员要求更高。
当然这也不能全怪他,也有我自己的问题。有没有可能是我把系统搞复杂了?
你想:如果我当天把这块甩给他,第二天就要交付,他做不完——是不是也因为我这套写法上手更慢?
- 可读性没那么直观,一眼看不出全貌;
- 要点开多个文件,才能拼出完整链路;
- 代码是一连串协作,得在脑子里先形成一张流程图,才知道它怎么走。
所以设计模式不是只有「解耦、好扩展」这些优点。它也有成本:复杂、上手慢、心智负担更高。 团队里如果有人暂时接不住这套抽象,就很容易退化成 if + 复制粘贴。
这件事给我最大的提醒是:模式不是会不会套名字,而是团队能不能共同维护这套结构。
收束(30 秒可直接背版)
我用开户讲策略模式:不同客户类型走不同套路,套路就是策略。大流程一致、细节不同,所以适合策略封装。
但后来同事没接住这套设计,直接复制代码加 if、加前端字段。这提醒我们:设计模式能降耦合、提扩展,也会抬高门槛。别为了模式而模式;但真有多类型、多分支、会持续扩展时,策略往往比一堆 if-else 更干净。
讲课小提示
- 先讲业务,再贴模式名:先说「不同客户不同套路」,最后点题「这就是策略」。
- 正反对比要狠一点:你的策略拆分 vs 他的
if+ 复制,反差最容易记住。 - 主动背锅半句:说「也可能是我写复杂了」,可信度更高,也不会显得在嘲同事。
- 落到行动建议:
- 类型稳定、逻辑很简单:别上模式;
- 类型会增、分支会厚、要并行改:再上策略;
- 交接时补一张时序 / 流程图,比丢一堆类给新人更重要。
附:白板板书结构
左边写「策略拆分」,右边写「if 复制」,对比最直观:
┌─────────────────────────┐ ┌─────────────────────────┐
│ 策略模式(正) │ │ if + 复制(反) │
│ 公共流程:校验→业务→后置 │ │ 原流程一份 │
│ 差异下沉:每类一个策略 │ │ 复制一份 + 前面加 if │
│ 加类型 = 新增策略类 │ │ 加类型 = 再复制 + 再加 if│
│ 易扩展 / 有门槛 │ │ 能跑 / 扩展性归零 │
└─────────────────────────┘ └─────────────────────────┘
