策略模式(Strategy Pattern)深入解析与实战应用

策略模式是一种常见的行为型设计模式,常用于替代大量冗余的 if-elseswitch-case 结构。它通过将一系列可互换的策略(行为)封装起来,使代码结构更清晰、可扩展性更强。

一、什么是策略模式?

策略模式(Strategy Pattern) 是指将一组算法或操作逻辑抽象为独立的"策略对象",根据上下文条件选择某一种策略执行。

一句话概括:把繁杂的 if-else 判断逻辑,变成"查表执行"。

二、策略模式结构图

plaintext 复制代码
┌────────────┐
│  Context   │ ← 运行环境,持有策略并调用
└────┬───────┘
     │
     ▼
┌────────────┐
│ Strategy A │ ← 实现某个行为
└────────────┘
┌────────────┐
│ Strategy B │ ← 实现另一个行为
└────────────┘

在 JavaScript/TypeScript 中,我们通常用对象映射(Map)来实现策略模式。

三、为什么要使用策略模式?

问题 策略模式解决方案
逻辑混乱 将不同逻辑解耦封装
if/else 重复臃肿 使用映射对象替代判断
新增/修改逻辑易出错 可扩展、遵循开闭原则
单元测试困难 策略单元独立、易测试

四、策略模式实战案例

✅ 1. 表单校验策略

ts 复制代码
const validateMap = {
  email: (val: string) => /\S+@\S+\.\S+/.test(val),
  phone: (val: string) => /^1\d{10}$/.test(val),
  username: (val: string) => val.length >= 3
};

function validate(type: string, value: string) {
  const fn = validateMap[type];
  return fn ? fn(value) : false;
}

✅ 2. Vue

动态视图策略

ts 复制代码
// strategies.ts
export const renderMap = {
  list: () => <ListView />,
  card: () => <CardView />,
  table: () => <TableView />
}
vue 复制代码
<template>
  <component :is="renderMap[viewMode]" />
</template>

🔁 五、从 if-else 到策略模式

原始写法(冗余):

ts 复制代码
function parseFile(type, content) {
  if (type === 'json') return JSON.parse(content)
  if (type === 'xml') return parseXML(content)
  if (type === 'csv') return parseCSV(content)
  throw new Error('Unknown type')
}

策略模式写法(优雅):

ts 复制代码
const parsers = {
  json: JSON.parse,
  xml: parseXML,
  csv: parseCSV
}

function parseFile(type: string, content: string) {
  const fn = parsers[type]
  if (!fn) throw new Error('Unknown type')
  return fn(content)
}

🧠 六、策略模式适用场景

  • 多分支逻辑(if/else 或 switch)

  • 规则判断:权限控制、表单验证、日志等级等

  • 插件架构:支付方式、导出格式等

  • 动态行为切换:主题切换、布局切换、组件渲染等

七、策略模式的进阶技巧

技巧 示例
支持注册/注销策略 StrategyMap.register('new', fn)
结合工厂模式 动态生成策略对象
封装为类或插件 统一维护,提升复用性
与配置驱动结合 使用配置文件/后端数据决定策略行为

八、与其他设计模式的区别

模式 相同点 区别
工厂模式 都封装行为创建 工厂关注对象创建,策略关注逻辑执行
状态模式 都有行为切换 状态模式强调状态变化,策略是行为选择
命令模式 都可执行操作 命令模式可撤销/排队,策略更偏向选择

✅ 九、总结

策略模式具有以下优点:

  • ✅ 解耦逻辑,清晰可读

  • ✅ 易于扩展,符合开闭原则

  • ✅ 易于测试,策略函数天然可单测

  • ✅ 非常适合动态渲染与业务逻辑分发

十、推荐封装方式(TypeScript 示例)

ts 复制代码
type StrategyFn = (args?: any) => any;

class StrategyManager {
  private strategies: Record<string, StrategyFn> = {};

  register(key: string, fn: StrategyFn) {
    this.strategies[key] = fn;
  }

  execute(key: string, args?: any) {
    const fn = this.strategies[key];
    if (!fn) throw new Error(`No strategy for key: ${key}`);
    return fn(args);
  }
}
相关推荐
郭老二1 天前
【前端】vue3:编译步骤
前端
不在逃避q1 天前
Trae/Vs Code/Cursor命令行无法跑npm命令
前端·arcgis·npm
夏殇之殁1 天前
包中创建自定义列表项。 . 使用自定义列表项进行数据绑定 . 将天气预报数据保存到本地内存表,通过LiveBindings进行显示。 ...
服务器·前端·javascript
The Chosen One9851 天前
高进度算法模板速记(待完善)
java·前端·算法
陈随易1 天前
MoonBit抓包模块pcap,查看电脑的每一次联网通信
前端·后端·程序员
新中地GIS开发老师1 天前
WebGIS开发学生作品|低空航天管理与航线规划系统
前端·javascript·webgis·三维gis开发
用户059540174461 天前
大模型对话记忆持久化踩坑实录:用 Playwright 自动化测了 300 次,终于揪出会话丢失的真凶
前端·css
丙氨酸長鏈1 天前
Web前端入门第 问:JavaScript 一个简单的 IndexedDB 数据库入门示例
前端·javascript·数据库
kyriewen1 天前
面试官让我手写虚拟列表——AI生成的版本,快速滚动几下就白屏了
前端·javascript·面试
IT_陈寒2 天前
Vite热更新失效?你可能漏了这个配置
前端·人工智能·后端