幾週前,我為 Globo Player 開發了解決方案,需要在執行過程中啟動和停用軟體中的特定行為。這種類型的需求通常透過鍊式條件語句來解決,例如 if-else 和 switch,但這種方法並不總是理想的。
在本文中,我提出了一個完美應對這項挑戰的解決方案,並且可以應用於不同的程式設計場景。
想像一下您剛剛到達一個未知的目的地。離開機場時,您有多種選擇前往酒店。最便宜的選擇是租一輛自行車,但這會花費更多時間。搭乘公車會貴一些,但可以更快、更安全地到達目的地。最後,租車是最快的選擇,但也是最貴的。
在這種情況下最重要的一點是要了解,無論選擇何種策略,最終目標都是相同的:到達酒店。
這個類比可以應用在軟體開發上。當我們處理不同流程尋求實現相同目標的場景時,我們可以使用策略設計模式來幫助我們。
想像一下,我們需要開發一個能夠根據客戶的帳戶類型計算費用的銀行系統,例如當前、儲蓄或保費。這些計算需要在運行時執行,這需要一個實作能夠正確地將程式碼流引導到適當的計算。
原則上,一種常見的方法是使用簡單的鍊式條件結構來快速、有效地解決問題:
class Banco { calcularTaxa(tipoConta, valor) { if (tipoConta === "corrente") { return valor * 0.02; // 2% de taxa } else if (tipoConta === "poupanca") { return valor * 0.01; // 1% de taxa } else if (tipoConta === "premium") { return valor * 0.005; // 0,5% de taxa } else { throw new Error("Tipo de conta não suportado."); } } } const banco = new Banco(); const taxa = banco.calcularTaxa("corrente", 1000); // Exemplo: R00 console.log(`A taxa para sua conta é: R$${taxa}`);
雖然此解決方案適用於簡單場景,但如果銀行將來需要添加另外五種帳戶類型,會發生什麼情況?
calcularTaxa(tipoConta, valor) { if (tipoConta === "corrente") { return valor * 0.02; // 2% de taxa } else if (tipoConta === "poupanca") { return valor * 0.01; // 1% de taxa } else if (tipoConta === "premium") { return valor * 0.005; // 0,5% de taxa } else if (tipoConta === "estudante") { return valor * 0.001; // 0,1% de taxa } else if (tipoConta === "empresarial") { return valor * 0.03; // 3% de taxa } else if (tipoConta === "internacional") { return valor * 0.04 + 10; // 4% + taxa fixa de R } else if (tipoConta === "digital") { return valor * 0.008; // 0,8% de taxa } else if (tipoConta === "exclusiva") { return valor * 0.002; // 0,2% de taxa } else { throw new Error("Tipo de conta inválido!"); } }
現在,程式碼開始顯示出嚴重的限制。讓我們探討一下這種方法的問題:
1。可擴充性低
每次需要新增新的帳戶類型時,calculateRate方法都需要修改。這不斷增加條件的數量,使程式碼更加複雜且難以管理。
2。高度依賴
費率計算邏輯與calculateRate方法完全耦合。對一種類型的帳戶進行更改可能會無意中影響其他帳戶,從而增加引入錯誤的風險。
3。程式碼重複
每種帳戶類型都會重複類似的片段,例如金額 * 費用。這會減少程式碼重複使用並違反DRY(不要重複自己)原則。
下一步,我們將看到策略模式如何解決這些問題,促進更乾淨、可擴展和模組化的程式碼。
為了避免上述問題,我們將在軟體中將每種帳戶類型視為獨立的實體。這是因為每種類型的帳戶都有特定的費用計算,並且可能有其他相關的未來行為。
我們不是建立一個帶有calculateRate方法來解決所有操作的Bank類,而是為每種類型的帳戶建立一個類別:
class Banco { calcularTaxa(tipoConta, valor) { if (tipoConta === "corrente") { return valor * 0.02; // 2% de taxa } else if (tipoConta === "poupanca") { return valor * 0.01; // 1% de taxa } else if (tipoConta === "premium") { return valor * 0.005; // 0,5% de taxa } else { throw new Error("Tipo de conta não suportado."); } } } const banco = new Banco(); const taxa = banco.calcularTaxa("corrente", 1000); // Exemplo: R00 console.log(`A taxa para sua conta é: R$${taxa}`);
這可確保每次計算操作都保持在您帳戶類型的特定範圍內。現在,我們針對每種類型的帳戶進行了隔離的行為:
但是,所需的帳戶選擇位於哪裡?
calcularTaxa(tipoConta, valor) { if (tipoConta === "corrente") { return valor * 0.02; // 2% de taxa } else if (tipoConta === "poupanca") { return valor * 0.01; // 1% de taxa } else if (tipoConta === "premium") { return valor * 0.005; // 0,5% de taxa } else if (tipoConta === "estudante") { return valor * 0.001; // 0,1% de taxa } else if (tipoConta === "empresarial") { return valor * 0.03; // 3% de taxa } else if (tipoConta === "internacional") { return valor * 0.04 + 10; // 4% + taxa fixa de R } else if (tipoConta === "digital") { return valor * 0.008; // 0,8% de taxa } else if (tipoConta === "exclusiva") { return valor * 0.002; // 0,2% de taxa } else { throw new Error("Tipo de conta inválido!"); } }
請注意,我們沒有建立鍊式決策結構(if-else),而是選擇在 Bank 類別的建構子中傳遞帳戶、策略。這允許 setConta 方法在實例化銀行時在執行時選擇所需的帳戶類型。費率計算將透過 this.conta.calcularTaxa(valor) 進行。
class ContaCorrente { calcularTaxa(valor) { return valor * 0.02; // 2% de taxa } } class ContaPoupanca { calcularTaxa(valor) { return valor * 0.01; // 1% de taxa } } class ContaPremium { calcularTaxa(valor) { return valor * 0.005; // 0,5% de taxa } }
透過這個模型,我們能夠以簡單的方式應用策略模式,確保更靈活、可擴展和低耦合的實作。
當您需要在運行時改變操作的行為,而不需要將執行程式碼直接耦合到不同的條件或類型時,策略模式是一個強大的解決方案。此模式非常適合操作行為可能根據上下文而變化以及替代方案彼此獨立的場景。
透過使用策略,我們保證程式碼變得更乾淨、模組化和靈活,同時促進系統更好的維護和擴展。
以上是使用策略模式避免過度調節的詳細內容。更多資訊請關注PHP中文網其他相關文章!