
原創(chuàng)作者:Yerassyl
原文鏈接:https://medium.com/@Yerazhas/refactoring-to-patterns-replace-conditional-logic-with-strategy-9970e057093a
代碼中最常見的復(fù)雜部分之一是復(fù)雜的條件邏輯.
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?-- Martin Fowler
今天我們將會(huì)探索怎么去用策略模式重構(gòu)條件邏輯代碼。目前已經(jīng)有很多關(guān)于重構(gòu)復(fù)雜條件邏輯代碼的方式,比如分解條件,組合方法,用多態(tài)性代替條件等等。
如果你需要在運(yùn)行時(shí)將一些算法與另一個(gè)算法交換,那么你應(yīng)該選擇策略模式(strategy)類。當(dāng)創(chuàng)建策略模式類的時(shí)候,有2種方式給他們傳數(shù)據(jù):
- 傳主類
- 像參數(shù)一樣傳遞數(shù)據(jù)
我們這里的 Loan 類是用來計(jì)算各種類型貸款的資本的,例如定期貸款,周轉(zhuǎn)金貸款,信用貸款。
class Loan {
var expiryDate: String?
var maturityDate: String?
func capital() -> Double {
if expiryDate != nil && maturityDate != nil {
return 10.0 * duration() * riskFactor()
}
if expiryDate != nil && maturityDate == nil {
if getUnusedPercentage() > 1.0 {
return 150.0 * getUnusedPercentage()
} else {
return 200.0 * getUnusedPercentage()
}
}
return 0.0
}
func duration() -> Double {
return 0.0
}
func riskFactor() -> Double {
return 0.0
}
func getUnusedPercentage() -> Double {
return 5.0
}
}
這個(gè)類有許多條件邏輯來確定貸款的類型。例如,expiryDate 為空,而且 maturityDate 不空的時(shí)候,就是一個(gè)定期貸款。
然后我們創(chuàng)建抽象的 CapitalStrategy 類(這里是protocol),還有TermLoanCapitalStrategy,RevolverCapitalStrategy子類,他們都實(shí)現(xiàn)自己的capital() -> Double 方法。
protocol CapitalStrategy {
func capital(loan: Loan) -> Double
func riskFactor() -> Double
}
extension CapitalStrategy {
func riskFactor() -> Double {
return 0.0
}
}
class RevolverCapitalStrategy: CapitalStrategy {
func capital(loan: Loan) -> Double {
return 250 * riskFactor()
}
}
class TermLoanCapitalStrategy: CapitalStrategy {
func capital(loan: Loan) -> Double {
if loan.expiryDate != nil && loan.maturityDate != nil {
return 10.0 * loan.duration() * riskFactor()
}
if loan.expiryDate != nil && loan.maturityDate == nil {
if loan.getUnusedPercentage() > 1.0 {
return 150.0 * loan.getUnusedPercentage()
} else {
return 200.0 * loan.getUnusedPercentage()
}
}
return 0.0
}
}
最后,我們用靜態(tài)方法來代替構(gòu)造函數(shù)。
final class Loan {
var expiryDate: String?
var maturityDate: String?
private var capitalStrategy: CapitalStrategy
private init(capitalStrategy: CapitalStrategy) {
self.capitalStrategy = capitalStrategy
}
static func termLoan() -> Loan {
return self.init(capitalStrategy: TermLoanCapitalStrategy())
}
static func revolver() -> Loan {
return self.init(capitalStrategy: RevolverCapitalStrategy())
}
func capital() -> Double {
return capitalStrategy.capital(loan: self)
}
func duration() -> Double {
return 0.0
}
func getUnusedPercentage() -> Double {
return 5.0
}
}
就這樣,我們單獨(dú)的方法有了明確的名稱和具體的策略對(duì)象(CapitalStrategy),這個(gè)對(duì)象實(shí)現(xiàn)了 capital() -> Double 方法。