有趣而有益的“管道模式”——电商支付用例

454 阅读2分钟

我想分享一个我最喜欢的、屡试不爽的设计模式——“管道模式”。所谓的“管道模式”,可以将其想象成一个“传输带”,或者“生产线”,它们传递一个东西,每一步进行相应操作,然后再传给下一环。在编程里,就是拿起一个实例对象,进行必要操作或修改,然后再传给下一个类,如此传下去。

可以想象这么一个订单处理的电商逻辑:

  1. 用户下单了
  2. 支付逻辑处理了支付
  3. 订单记录,或者发货单生成了,并发送给了用户
  4. 订单发送到了你的ERP系统中了,交付生产了
  5. 订单物品打包后发货了
  6. 用户收到了一封感谢信

虽然借助于某些状态机(state-machine,可大致理解成管理状态的机器系统),这整个流程会更好处理些,但是这期间,很显然展示出了一个“管道”、“流程”或“步骤”概念。

在这些所有的步骤或管道中,有一个基本的常量——这个订单,它被传递到了这个过程的每一步,直到最后处理完。

如果你之前搞过类似的逻辑,那么十有八九你会在你的比如说Order.php里,搞类似的这么一堆乱糟糟的代码:

if ($order->getStatus() === 'success') {
    $this->getErpAdapter()->sendOrder($order);
}
// 此处省略了一百个if判断

这样的代码,要理解它,你就得一行行的紧盯着看,又乱又费时间,让人没心情看完。

Any fool can write code that a computer can understand. Good programmers write code that humans can understand.

任何一个傻子,都可以写出能让计算机执行的代码;但是只有好的程序员,才能写出让人看得懂的代码。

——Martin Fowler

这是我喜欢的一个引用。那么现在,看看下面的代码:

$pipeline = (new Pipeline)
    ->pipe(new createOrder)
    ->pipe(new processPayment)
    ->pipe(new sendInvoice)
    ->pipe(new exportOrder);
$pipeline->process($order);

现在还会有人抱怨“可读性”吗?不会了吧。

这样来写,同样也让你在“可测试性”上,以及单一职责原则上,获得巨大胜利——因为你现在每一块代码只做一件事儿,或者相关的两件也行,然后就传给下一个类了,职责非常简单清晰。这样整个流程的每一步都是可测试的,都可以轻易mock,甚至整个的管道流程也是可测试的。

好了,由于本文较长,剩下的请移步我们原文发布处阅读,以下是剩下的目录结构

原文链接: www.pilishen.com/posts/the-p…