杀死 if...else
文章本来是上周要写的,结果一拖再拖就拖到了今天。
最近在给系统做一些重构工作,至于为什么要重构其实可以另开一个话题来展开,简单来说,如果系统能正常跑就没必要为了重构而重构,重构真正目的,主要是为了适应产品的迭代,让系统保持良好的扩展性。
我在重构过程中,发现支付逻辑充斥着坏味道,主要代码是下面这样的,我把实现的细节都省略了,当然实际代码比这个要长很多。
def pay(pay_type):
if pay_type =='alipay':
alipay.pay()
elif pay_type == 'wechat':
wechat.pay()
elif pay_type == 'unionpay':
unionpay.pay()
这段代码的使用场景是满足用户可以选择不同的支付方式完成付款操作,对应后端的代码,你肯定能想到最简单的实现方式就是上面的if ... else 语句。
随着你的业务不断扩大,产品经理跑过来跟你说,还需要接入多种支付方式,你的if else 代码也跟着越来越长了。这带来的一个问题就是系统的可扩展性差,后续的维护会变得举步维艰。
在《重构》这本书,讲到一个重构的原则,面对冗长的if else 语句, 我们可以利用面向对象的多态特性将if else 语句替换掉。
什么是多态
多态(Polymorphism)这个概念最早来自于生物学,表示的是同一物种在同一种群中存在两种或多种明显不同的表型。比如:在南美种群中存在两种颜色的美洲虎:浅黄色的和黑色的。
在面向对象编程思想中,这个概念表达的是具有共性的类型,在执行相同的行为时,会体现出不同的实现方式。我们可以简称为:相同的行为,不同的实现。
在支付这个场景中,支付方式就是一种典型的多态,无论是支付宝还是微信或者是其他支付,他们都有一种相同的行为:提供支付功能,可以肯定的是不同的支付方式都有它自己的不同的实现方式。
那么,如何将多态这种特性应用在我们的代码中来呢?
第一步:给每一种支付类型定义一个类,里面的pay方法用来实现具体的支付逻辑,对应每一个条件分支
class Pay:
def pay(self):
raise NotImplementedError()
class Alipay(Pay):
def pay(self):
# 这是支付宝的实现方式
class WechatPay(Pay):
def pay(self):
# 这是微信支付的实现方式
我这里使用了面向对象中另一个特性:继承。通过继承,让每一个具体的支付类型都必须实现pay方法。当然继承是可选的,因为在动态语言python中,多态不需要建立在继承的基础之上,只需要有 pay方法,不管是不是Pay的子类都可以当做一种支付方式类处理。
第二步:构建支付实例
我们可以用一个字典或者工厂方法来实现通过一个支付类型来找到对应的具体支付实例对象。
lookup = {
"alipay": Alipay(),
"wechat": Wechatpay()
}
第三步:替换 if else
def pay(pay_type):
lookup.get(pay_type).pay()
现在再来看pay函数是不是简单多了,和冗长的if else 语句说再见吧
如果未来需要增加其他支付方式,我们完全不需要再去修改pay函数,你只要去实现一个XxxPay的类就可以。
if ... else 就这样被干掉了。
最后,我想告诉大家的是,并不是什么场景都非要用多态来解决 if else 语句的。如果 if else 中的逻辑本来就很清晰,就没必要生搬硬套用多态去解决了。
刘志军,一个写了10+年代码的码农,欢迎关注