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

一、一个被 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 来决定"怎么处理"时,就是策略模式该上场的时候。把条件分支替换成配置对象,把每种逻辑封装成独立策略,代码结构会立刻清晰起来。