殺死 if...else
↑ 關(guān)注 + 星標(biāo) ,每天學(xué)Python新技能
后臺回復(fù)【大禮包】送你Python自學(xué)大禮包
文章本來是上周要寫的,結(jié)果一拖再拖就拖到了今天。
最近在給系統(tǒng)做一些重構(gòu)工作,至于為什么要重構(gòu)其實(shí)可以另開一個(gè)話題來展開,簡單來說,如果系統(tǒng)能正常跑就沒必要為了重構(gòu)而重構(gòu),重構(gòu)真正目的,主要是為了適應(yīng)產(chǎn)品的迭代,讓系統(tǒng)保持良好的擴(kuò)展性。
我在重構(gòu)過程中,發(fā)現(xiàn)支付邏輯充斥著壞味道,主要代碼是下面這樣的,我把實(shí)現(xiàn)的細(xì)節(jié)都省略了,當(dāng)然實(shí)際代碼比這個(gè)要長很多。
def pay(pay_type):
if pay_type =='alipay':
alipay.pay()
elif pay_type == 'wechat':
wechat.pay()
elif pay_type == 'unionpay':
unionpay.pay()
這段代碼的使用場景是滿足用戶可以選擇不同的支付方式完成付款操作,對應(yīng)后端的代碼,你肯定能想到最簡單的實(shí)現(xiàn)方式就是上面的if ... else 語句。
隨著你的業(yè)務(wù)不斷擴(kuò)大,產(chǎn)品經(jīng)理跑過來跟你說,還需要接入多種支付方式,你的if else 代碼也跟著越來越長了。這帶來的一個(gè)問題就是系統(tǒng)的可擴(kuò)展性差,后續(xù)的維護(hù)會變得舉步維艱。
在《重構(gòu)》這本書,講到一個(gè)重構(gòu)的原則,面對冗長的if else 語句, 我們可以利用面向?qū)ο蟮亩鄳B(tài)特性將if else 語句替換掉。
什么是多態(tài)
多態(tài)(Polymorphism)這個(gè)概念最早來自于生物學(xué),表示的是同一物種在同一種群中存在兩種或多種明顯不同的表型。比如:在南美種群中存在兩種顏色的美洲虎:淺黃色的和黑色的。

在面向?qū)ο缶幊趟枷胫?,這個(gè)概念表達(dá)的是具有共性的類型,在執(zhí)行相同的行為時(shí),會體現(xiàn)出不同的實(shí)現(xiàn)方式。我們可以簡稱為:相同的行為,不同的實(shí)現(xiàn)。
在支付這個(gè)場景中,支付方式就是一種典型的多態(tài),無論是支付寶還是微信或者是其他支付,他們都有一種相同的行為:提供支付功能,可以肯定的是不同的支付方式都有它自己的不同的實(shí)現(xiàn)方式。
那么,如何將多態(tài)這種特性應(yīng)用在我們的代碼中來呢?
第一步:給每一種支付類型定義一個(gè)類,里面的pay方法用來實(shí)現(xiàn)具體的支付邏輯,對應(yīng)每一個(gè)條件分支
class Pay:
def pay(self):
raise NotImplementedError()
class Alipay(Pay):
def pay(self):
# 這是支付寶的實(shí)現(xiàn)方式
class WechatPay(Pay):
def pay(self):
# 這是微信支付的實(shí)現(xiàn)方式
我這里使用了面向?qū)ο笾辛硪粋€(gè)特性:繼承。通過繼承,讓每一個(gè)具體的支付類型都必須實(shí)現(xiàn)pay方法。當(dāng)然繼承是可選的,因?yàn)樵趧討B(tài)語言python中,多態(tài)不需要建立在繼承的基礎(chǔ)之上,只需要有 pay方法,不管是不是Pay的子類都可以當(dāng)做一種支付方式類處理。
第二步:構(gòu)建支付實(shí)例
我們可以用一個(gè)字典或者工廠方法來實(shí)現(xiàn)通過一個(gè)支付類型來找到對應(yīng)的具體支付實(shí)例對象。
lookup = {
"alipay": Alipay(),
"wechat": Wechatpay()
}
第三步:替換 if else
def pay(pay_type):
lookup.get(pay_type).pay()
現(xiàn)在再來看pay函數(shù)是不是簡單多了,和冗長的if else 語句說再見吧
如果未來需要增加其他支付方式,我們完全不需要再去修改pay函數(shù),你只要去實(shí)現(xiàn)一個(gè)XxxPay的類就可以。
if ... else 就這樣被干掉了。
最后,我想告訴大家的是,并不是什么場景都非要用多態(tài)來解決 if else 語句的。如果 if else 中的邏輯本來就很清晰,就沒必要生搬硬套用多態(tài)去解決了。


