一、什么是策略模式???
策略模式(Strategy Pattern)屬于??行為型設計模式??。核心思路是將一組??可替換的算法??封裝在獨立的類中,使它們可以在運行時動態切換,同時使客戶端代碼與具體算法解耦。它包含三個核心角色:
- ??策略接口(Strategy Interface)??:定義算法的方法簽名
- ??具體策略(Concrete Strategies)??:實現具體算法邏輯
- ??上下文(Context)??:持有一個策略對象,并調用其方法
??通俗比喻??:把算法當作「插件」,客戶端只需要選擇對應插件插入到主流程中,不需要關注插件內部實現。
??二、適用場景??
_以下場景常見于前端開發:_
- ??同類功能的多算法切換??
👉 表單驗證(郵箱、手機號、身份證等校驗規則)、數據導出(CSV、Excel、PDF格式)、圖表渲染(折線圖、柱狀圖) - ??需要動態選擇行為的場景??
👉 動態折扣計算(滿減、折扣券、積分抵扣)、權限校驗(不同角色對應不同校驗規則) - ??消除臃腫的條件分支??
👉 存在大量?if-else
?或?switch-case
?的場景(如老代碼中的支付方式處理) - ??需要隱藏復雜算法的實現??
👉 地圖路徑規劃(步行、駕車、公交策略)、動畫緩動函數(linear、ease-in)
??三、實戰代碼示例??
??案例1:表單驗證策略??
// 策略接口:定義 validate 方法
class ValidationStrategy {validate(value) {throw new Error("必須實現 validate 方法!");}
}// 具體策略:非空校驗
class RequiredValidation extends ValidationStrategy {validate(value) {return value.trim() !== "";}
}// 具體策略:手機號校驗
class MobileValidation extends ValidationStrategy {validate(value) {return /^1[3-9]\d{9}$/.test(value);}
}// 上下文類:管理當前策略
class ValidatorContext {constructor(strategy) {this.strategy = strategy;}setStrategy(strategy) {this.strategy = strategy;}execute(value) {return this.strategy.validate(value);}
}// 使用示例
const validator = new ValidatorContext(new RequiredValidation());
console.log(validator.execute("")); // 輸出 falsevalidator.setStrategy(new MobileValidation());
console.log(validator.execute("13800138000")); // 輸出 true
??代碼亮點??:
- 添加新校驗規則只需新增策略類,無須修改?
ValidatorContext
- 客戶端通過?
.setStrategy()
?動態切換算法
??案例2:動態數據導出(常用功能增強)??
// 策略接口:導出方法
class ExportStrategy {export(data) {throw new Error("必須實現 export 方法");}
}// 具體策略-導出為 CSV
class CsvExport extends ExportStrategy {export(data) {const csvContent = data.map(row => row.join(",")).join("\n");console.log(`導出 CSV 成功,內容:${csvContent}`);}
}// 具體策略-導出為 Excel(偽代碼)
class ExcelExport extends ExportStrategy {export(data) {// 假裝調用了 Excel 庫console.log("生成 Excel 文件并下載");}
}// 上下文(可與 UI 結合)
class Exporter {constructor() {this.strategy = new CsvExport(); // 默認策略}setFormat(format) {if (format === 'csv') {this.strategy = new CsvExport();} else if (format === 'excel') {this.strategy = new ExcelExport();}}executeExport(data) {this.strategy.export(data);}
}// 使用示例
const exporter = new Exporter();
exporter.setFormat('excel');
exporter.executeExport([['Name', 'Age'], ['John', 30]]);
??應用場景??:
不同導出格式的代碼集中到策略類中,避免主模塊代碼混亂。
??四、開發建議與避坑指南??
??推薦做法??:
- ??組合優于繼承??:
用策略對象組合到上下文類,而非通過繼承實現多態 - ??接口約束??:TypeScript 更優
interface Strategy {execute(data: any): void; }
- ??策略命名清晰??:
用?MobileValidationStrategy
?而非?Strategy1
,便于維護 - ??無狀態策略??:
盡量將策略設計為無狀態(純函數),可通過單例復用
??常見陷阱??:
- ??過度設計??:
👉 若只有1~2種固定算法,直接?if-else
?更簡單 - ??客戶端感知策略細節??:
👉 違反迪米特法則,應當由上下文類處理策略選擇 - ??策略間參數不一致??:
👉 校驗策略統一接收字符串,而非有的需要?value
,有的需要?formData
- ??性能損耗??:
👉 頻繁創建策略對象時,可考慮對象池緩存
?
策略模式是應對??算法多樣化??和??動態切換需求??的強大工具,前端開發中使用頻率較高。
正確使用可顯著提升代碼可維護性,但在簡單場景下需權衡是否引入復雜度。關鍵在于??識別行為的變化點??,將其獨立出來。