支付回调的代码里,十二个渠道一字排开,if-else 写了三百多行。每加一个渠道,就复制一段,改两个字段。后来我们把策略模式和工厂模式拼在一起用,主流程只剩二十行。
拆法很简单。先定义一个接口,比如 PaymentStrategy,里面一个 pay 方法。每个渠道一个实现类,微信的、支付宝的、银联的,各自处理签名和参数。这部分就是策略模式。
工厂只做一件事:按类型取实例
策略有了,调用方还得知道用哪个实现。这时候用工厂,把类型和实现绑定起来。Spring 项目里最省事的做法,是让每个实现类带一个类型值,启动时收进 Map:
Map<String, PaymentStrategy> map = strategies.stream().collect(Collectors.toMap(PaymentStrategy::type, s -> s));调用的时候一行 map.get(type).pay(order)。新增渠道只要加一个类,主流程不用动。这比在工厂里写 switch 更灵活,因为 switch 每加一个分支还是要改文件。
别把工厂做成另一坨 if
有人照着写,工厂里还是 if channel 等于 wx 就 new WxPay,等于把 if 从业务挪到了工厂,行数没少。工厂的职责是取对象,判断逻辑应该收敛到注册表里。
如果渠道有前置校验、限额、退款这些差异,可以把这些也放进接口。但接口别做太大,一个方法管支付,一个管退款,够用就行。接口一大,每个实现类都要写空方法,反而难维护。
什么时候不值得拆
只有两个渠道、逻辑还没稳定的时候,别急着上模式。策略加工厂会多出五六个类,读代码要跳来跳去。等到分支超过五个、每加一个渠道都要改主流程,再拆。重构的时机比模式本身重要。