前端开发中的策略模式——告别 if-else 的优雅之道

策略模式是前端开发中最实用的设计模式之一。它不复杂,却能显著提升代码的可维护性。本文从最典型的表单校验场景出发,给出策略模式的完整实现。

一、一个被 if-else 淹没的场景

假设你在做后台管理系统的表单,需要校验不同类型的字段:邮箱、手机号、密码、身份证号等。最常见的写法是这样:

javascript 复制代码
function validate(value, type) {
  if (type === 'email') {
    return /\S+@\S+\.\S+/.test(value) ? '' : '邮箱格式错误';
  } else if (type === 'phone') {
    return /^1[3-9]\d{9}$/.test(value) ? '' : '手机号格式错误';
  } else if (type === 'password') {
    return value.length >= 6 ? '' : '密码至少6位';
  } else if (type === 'idCard') {
    // 身份证校验逻辑...
  }
  return '';
}

问题很明显:新增一种校验类型,就要改动这个函数。随着业务发展,这个函数会越来越长,每次改动都可能影响已有逻辑。这就是策略模式要解决的问题。

二、策略模式的核心思想

定义一系列算法,把它们封装成可互换的策略函数,用配置对象代替条件分支 。调用方根据场景选择策略,而不是用 if-else 硬编码分支逻辑。

用在表单校验上:

javascript 复制代码
// 1. 把每种校验规则封装成独立策略
const validators = {
  required: (val) => (val && val.trim() ? '' : '必填'),
  email: (val) => (/^\S+@\S+\.\S+$/.test(val) ? '' : '邮箱格式错误'),
  phone: (val) => (/^1[3-9]\d{9}$/.test(val) ? '' : '手机号格式错误'),
  minLength: (min) => (val) => (val.length >= min ? '' : `最少${min}位`),
};

// 2. 通用校验器------策略调度
function validate(value, rules) {
  for (const rule of rules) {
    const fn = typeof rule === 'function' ? rule : validators[rule];
    const error = fn(value);
    if (error) return error;
  }
  return '';
}

使用:

javascript 复制代码
validate('hello@test.com', ['required', 'email']);            // ''
validate('hi', ['required', 'email']);                         // '邮箱格式错误'
validate('abc', ['required', validators.minLength(6)]);        // '最少6位'

新增任何校验规则,只需要在 validators 对象上加一个方法,完全不用改动 validate 函数。这就是策略模式的价值:对扩展开放,对修改关闭。

在 React 中配合 Ant Design 使用时同样清晰:

tsx 复制代码
<Form.Item
  name="email"
  rules={[{ validator: (_, val) => validators.email(val) }]}
>
  <Input />
</Form.Item>

三、另外两个高频应用场景

1. 状态映射------数字变 UI

接口返回订单状态 0、1、2,页面需要展示不同颜色的标签。不用策略模式时,往往在 render 里写一堆三元表达式。改用配置对象:

javascript 复制代码
const ORDER_STATUS_MAP = {
  0: { text: '待支付', color: 'orange' },
  1: { text: '已支付', color: 'green' },
  2: { text: '已取消', color: 'gray' },
};

function getStatusConfig(status) {
  return ORDER_STATUS_MAP[status] ?? { text: '未知', color: 'gray' };
}
tsx 复制代码
// React 表格中
render: (status) => {
  const config = getStatusConfig(status);
  return <Tag color={config.color}>{config.text}</Tag>;
}

日志级别、用户角色、通知类型等场景同理------用配置对象统一管理映射关系,新增状态只需加一行。

2. 环境适配------不同环境不同行为

开发环境需要打印日志到控制台,生产环境需要上报到 Sentry。策略模式可以配合构建工具的 Tree Shaking,在打包时只保留当前环境需要的代码:

javascript 复制代码
// loggers/dev.ts
export const logger = {
  error: (msg) => console.error(msg),
  warn: (msg) => console.warn(msg),
};

// loggers/prod.ts
export const logger = {
  error: (msg, extra) => Sentry.captureMessage(msg, { extra }),
  warn: () => {},
};
javascript 复制代码
// 动态导入,构建时只保留一个文件
const logger = await import(`./loggers/${import.meta.env.MODE}.ts`);
logger.error('出错了');

环境切换、支付渠道、地图 SDK 选择------凡是需要根据某个条件选择不同处理方式的场景,都可以用策略模式。

四、总结

策略模式是最实用的前端设计模式之一。它用配置对象代替条件分支,让代码对扩展开放、对修改关闭。在前端开发中,它最常见的落地场景包括:

  • 表单校验:不同字段、不同规则用策略函数组合
  • 状态映射:数字/枚举 → UI 组件的映射表
  • 环境适配:开发、测试、生产的不同行为策略
  • 格式化器:日期、金额、文件大小的多种格式化策略

当你发现自己在写大量 if-else 或 switch 来决定"怎么处理"时,就是策略模式该上场的时候。把条件分支替换成配置对象,把每种逻辑封装成独立策略,代码结构会立刻清晰起来。

相关推荐
এ慕ོ冬℘゜15 小时前
如何在 HTML 中嵌入音频和视频?
前端·html·音视频
2501_9445215921 小时前
Ramda 跨端三方库仓颉适配全流程
开发语言·javascript·flutter·php
考研保研资料分享1 天前
211公共管理保研北航行政管理:五校考核、论文追问与择校复盘
面试
考研保研资料分享1 天前
985工科跨保上财应用统计:数学笔试、匿名面试与机试复盘
面试·职场和发展
Ken_11151 天前
小体积附件下载正常,大附件下载异常
javascript
变与不变8061 天前
jQuery怎么使用
前端·javascript
神膘护体小月半1 天前
flex 布局的 order 属性
前端·css
paopaokaka_luck1 天前
流浪动物救助与收养系统(DeepSeek AI对话、 ECharts多维分析、救助流程衔接、领养与回访衔接、 捐赠确认与公示、志愿者协作)
java·前端·javascript·人工智能·mysql·echarts·推荐算法
仰望.1 天前
vue 表格组件 vxe-table 树表格懒加载支持拖拽排序的详细用法
前端·javascript·vue.js·vxe-table
前端 贾公子1 天前
vite-plugin-uni-manifest 升级指南
前端