什么是策略模式?

策略模式(Strategy Pattern)是一种行为型设计模式,它定义了一系列算法(或行为),并将每个算法封装起来,使它们可以相互替换。策略模式让算法的变化独立于使用算法的客户端,从而实现 “算法灵活切换” 和 “客户端与算法解耦”。

其核心思想是:将可变的行为(算法)提取为独立的策略类,客户端通过组合而非继承的方式使用这些策略,避免用大量条件判断(if-else 或 switch)来选择不同行为。

策略模式的核心角色

  1. 策略接口(Strategy):定义所有策略类的公共接口,规定策略必须实现的方法(如算法执行方法)。
  2. 具体策略(ConcreteStrategy):实现策略接口的具体算法类,封装不同的行为逻辑。
  3. 上下文(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: {}(无错误,验证通过)

代码说明

  1. 具体策略usernameStrategystrongPasswordStrategy 等对象封装了不同的验证算法,均实现了 validate 方法(策略接口的约定),负责具体的规则判断。
  2. 上下文(FormValidator)
    • 通过 addField 方法将字段与策略关联(如 “username” 对应用户名验证策略)。
    • validate 方法接收表单数据,遍历所有字段,调用对应策略的 validate 方法,汇总验证结果。客户端只需调用 validate 即可,无需关心具体验证规则。
  3. 核心优势
    • 消除条件判断:无需用 if-else 判断字段类型再执行对应验证,而是通过策略直接映射。
    • 灵活切换:修改验证规则时,只需替换策略(如密码从 strongPasswordStrategy 改为 simplePasswordStrategy),无需修改验证器代码。
    • 易于扩展:新增验证规则(如手机号验证),只需添加新的策略对象并关联字段,符合 “开闭原则”。

策略模式的常见应用场景

  • 算法切换:如排序算法(快速排序、冒泡排序)、支付方式(支付宝、微信支付)的动态选择。
  • 规则验证:如表单验证、权限校验等多规则场景。
  • 行为定制:如游戏角色的技能系统(不同角色使用不同技能策略)。

与简单工厂模式的区别

策略模式聚焦于 “算法的封装与切换”,客户端需要知道所有策略并主动选择;简单工厂模式聚焦于 “对象的创建”,客户端无需知道具体产品,由工厂决定创建哪种对象。两者可结合使用(如工厂负责创建策略对象,策略模式负责使用策略)。

策略模式的核心是 “分离变化的算法,封装不变的骨架”,让系统更灵活、更易于维护。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐