什么是策略模式?JavaScript 实现一个策略模式的示例
·
什么是策略模式?
策略模式(Strategy Pattern)是一种行为型设计模式,它定义了一系列算法(或行为),并将每个算法封装起来,使它们可以相互替换。策略模式让算法的变化独立于使用算法的客户端,从而实现 “算法灵活切换” 和 “客户端与算法解耦”。
其核心思想是:将可变的行为(算法)提取为独立的策略类,客户端通过组合而非继承的方式使用这些策略,避免用大量条件判断(if-else 或 switch)来选择不同行为。
策略模式的核心角色
- 策略接口(Strategy):定义所有策略类的公共接口,规定策略必须实现的方法(如算法执行方法)。
- 具体策略(ConcreteStrategy):实现策略接口的具体算法类,封装不同的行为逻辑。
- 上下文(Context):持有一个策略接口的引用,负责将客户端的请求委托给具体策略执行,客户端通过上下文间接使用策略。
JavaScript 实现策略模式示例:表单验证
以下以 “表单验证” 为例,实现策略模式。场景是:一个注册表单需要验证不同字段(用户名、密码、邮箱),每种字段的验证规则不同(如用户名长度、密码强度、邮箱格式),且可能需要灵活切换验证规则(如密码强度从 “简单” 改为 “复杂”)。
代码实现 - javascript
// -------------- 1. 具体策略:验证规则(封装不同算法)--------------
// 用户名验证:长度 3-10 位
const usernameStrategy = {
validate(value) {
if (!value) return "用户名不能为空";
if (value.length < 3 || value.length > 10) return "用户名长度必须为 3-10 位";
return null; // 验证通过
}
};
// 密码验证(简单规则):至少 6 位
const simplePasswordStrategy = {
validate(value) {
if (!value) return "密码不能为空";
if (value.length < 6) return "密码长度至少 6 位";
return null;
}
};
// 密码验证(复杂规则):至少 8 位,包含字母和数字
const strongPasswordStrategy = {
validate(value) {
if (!value) return "密码不能为空";
if (value.length < 8) return "密码长度至少 8 位";
if (!/[a-zA-Z]/.test(value) || !/\d/.test(value)) return "密码必须包含字母和数字";
return null;
}
};
// 邮箱验证:符合邮箱格式
const emailStrategy = {
validate(value) {
if (!value) return "邮箱不能为空";
const reg = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!reg.test(value)) return "邮箱格式不正确";
return null;
}
};
// -------------- 2. 上下文:表单验证器(使用策略)--------------
class FormValidator {
constructor() {
this.strategies = {}; // 存储字段与策略的映射(如 { username: usernameStrategy })
}
// 为字段添加验证策略
addField(fieldName, strategy) {
this.strategies[fieldName] = strategy;
}
// 执行验证(委托给具体策略)
validate(formData) {
const errors = {};
// 遍历所有字段,调用对应策略的 validate 方法
Object.entries(this.strategies).forEach(([fieldName, strategy]) => {
const value = formData[fieldName];
const error = strategy.validate(value);
if (error) {
errors[fieldName] = error;
}
});
return errors; // 返回验证结果(键:字段名,值:错误信息)
}
}
// -------------- 3. 客户端使用 --------------
// 创建验证器(上下文)
const validator = new FormValidator();
// 配置验证策略(可灵活切换)
validator.addField("username", usernameStrategy);
validator.addField("password", strongPasswordStrategy); // 使用复杂密码规则
validator.addField("email", emailStrategy);
// 验证表单数据
const formData1 = {
username: "ab", // 长度不足
password: "123456", // 不符合复杂规则
email: "test" // 格式错误
};
const errors1 = validator.validate(formData1);
console.log("验证结果1:", errors1);
// 输出:
// 验证结果1: {
// username: '用户名长度必须为 3-10 位',
// password: '密码长度至少 8 位',
// email: '邮箱格式不正确'
// }
// 切换密码策略为简单规则
validator.addField("password", simplePasswordStrategy);
const formData2 = {
username: "alice",
password: "123456", // 符合简单规则
email: "alice@example.com"
};
const errors2 = validator.validate(formData2);
console.log("验证结果2:", errors2); // 输出:验证结果2: {}(无错误,验证通过)
代码说明
- 具体策略:
usernameStrategy、strongPasswordStrategy等对象封装了不同的验证算法,均实现了validate方法(策略接口的约定),负责具体的规则判断。 - 上下文(FormValidator):
- 通过
addField方法将字段与策略关联(如 “username” 对应用户名验证策略)。 validate方法接收表单数据,遍历所有字段,调用对应策略的validate方法,汇总验证结果。客户端只需调用validate即可,无需关心具体验证规则。
- 通过
- 核心优势:
- 消除条件判断:无需用
if-else判断字段类型再执行对应验证,而是通过策略直接映射。 - 灵活切换:修改验证规则时,只需替换策略(如密码从
strongPasswordStrategy改为simplePasswordStrategy),无需修改验证器代码。 - 易于扩展:新增验证规则(如手机号验证),只需添加新的策略对象并关联字段,符合 “开闭原则”。
- 消除条件判断:无需用
策略模式的常见应用场景
- 算法切换:如排序算法(快速排序、冒泡排序)、支付方式(支付宝、微信支付)的动态选择。
- 规则验证:如表单验证、权限校验等多规则场景。
- 行为定制:如游戏角色的技能系统(不同角色使用不同技能策略)。
与简单工厂模式的区别
策略模式聚焦于 “算法的封装与切换”,客户端需要知道所有策略并主动选择;简单工厂模式聚焦于 “对象的创建”,客户端无需知道具体产品,由工厂决定创建哪种对象。两者可结合使用(如工厂负责创建策略对象,策略模式负责使用策略)。
策略模式的核心是 “分离变化的算法,封装不变的骨架”,让系统更灵活、更易于维护。
更多推荐


所有评论(0)