在 React 前端開發時,常常會需要在不同的元件、hook、utils 中寫一些邏輯。
有些時候,使用策略模式會很有幫助,這篇文章給您參考。
Shotgun Surgery 是一種程式寫很爛的信號。想對程式規格做一點小修改,需要改一大堆地方。
在專案中通常如何發生?假設我們需要為產品寫一個報價卡片,我們根據客戶所在國家,調整價格、貨幣、折扣方式和文字說明:
大多數工程師可能會這樣寫:
元件:PricingCard
、PricingHeader
、PricingBody
。
Utility functions:getDiscountMessage
(在 utils/discount.ts 中),formatPriceByCurrency
(在 utils/price.ts 中)。
PricingBody
元件會計算最終價格。
完整程式碼範例:https://codesandbox.io/s/react-strategy-pattern-problem-h59r02?from-embed
現在假設我們需要更改一個國家/地區的定價計劃,或為另一個國家/地區添加新的定價計劃。您將如何處理這段修改?您必須至少修改 3 個地方,並向已經滿亂的 if-else
區塊添加更多條件:
修改 PricingBody
組件。
修改 getDiscountMessage
函數。
修改 formatPriceByCurrency
函數。
如果您聽說過 S.O.L.I.D 原則,我們已經違反了前 2 條原則:單一職責原則和開閉原則。
策略模式非常簡單。我們可以簡單的理解為,每個國家的定價方案都是一個策略。在那個策略類別中,會實現該策略的所有相關邏輯。
假設您熟悉 OOP,我們可以有一個實現共享/公共邏輯的抽像類別(PriceStrategy
),然後具有不同邏輯的策略將繼承該抽像類別。 PriceStrategy
抽像類別如下所示:
import { Country, Currency } from '../../types';
abstract class PriceStrategy {
protected country: Country = Country.AMERICA;
protected currency: Currency = Currency.USD;
protected discountRatio = 0;
getCountry(): Country {
return this.country;
}
formatPrice(price: number): string {
return [this.currency, price.toLocaleString()].join('');
}
getDiscountAmount(price: number): number {
return price * this.discountRatio;
}
getFinalPrice(price: number): number {
return price - this.getDiscountAmount(price);
}
shouldDiscount(): boolean {
return this.discountRatio > 0;
}
getDiscountMessage(price: number): string {
const formattedDiscountAmount = this.formatPrice(
this.getDiscountAmount(price)
);
return `It's lucky that you come from ${this.country}, because we're running a program that discounts the price by ${formattedDiscountAmount}.`;
}
}
export default PriceStrategy;
我們只需將實例化的策略作為 prop 傳遞給 PricingCard 元件:
<PricingCard price={7669} strategy={new JapanPriceStrategy()} />
PricingCard
的 props 定義為:
interface PricingCardProps {
price: number;
strategy: PriceStrategy;
}
同樣,如果您了解 OOP,那麼我們不僅在使用繼承,而且還在此處使用多態性(Polymorphism)。
完整程式碼範例:https://codesandbox.io/s/react-strategy-pattern-solution-mm0cvm?from-embed
使用這個解決方案,我們只需要添加一個新的策略類別,而不需要修改任何現有程式碼。這樣,我們也滿足了 S.O.L.I.D 原則。
因為我們在 React 程式碼中檢測到程式碼發臭:Shotgun Surgery,所以我們使用了策略模式來解決它。
現在邏輯都存在一個地方,不再分佈在許多地方。
以上是 Strategy Pattern 的簡單說明,希望對您有幫助。