JavaScript - 策略模式在开发中的应用

1. 什么是策略模式

策略模式的定义是:定义一系列的算法,把它们一个个封装起来,并且使它们可以互相替换。

它最主要的目的是将算法与环境区分开,让算法与环境之间解耦。

策略模式由两部分组成:

  1. 第一部分是策略类strategy,策略类负责封装多个算法
  2. 第二部分是环境类context,环境类负责调用策略类当中的某个算法

2. 策略模式示例

在使用策略模式时,需要将算法从环境中提取出来,封装到策略中,例如在未使用策略模式之前,你判断渲染组件的代码有可能是这样:

xml 复制代码
<template>
  <UserBoard v-if="userType === 'user'" />
  <StaffBoard v-else-if="userType === 'staff'" />
</template>

<script setup>
import { UserBoard } from '@/view/busi/user/userBoard.vue';
import { StaffBoard } from '@/view/busi/staff/staffBoard.vue';

const props = defineProps({
  userType: {
   type: String,
   required: true
  }
})
</script>

这种写法在组件较少的情况下是没有问题的,但需要判断渲染的组件一多,代码就很丑陋,可读性会变得很差,在这种情况下,我们就可以使用策略模式去定义一个映射。

使用了策略模式之后:

xml 复制代码
<template>
  <component :is="strategies[userType]"></component>
</template>

<script setup>
import { UserBoard } from '@/view/busi/user/userBoard.vue';
import { StaffBoard } from '@/view/busi/staff/staffBoard.vue';

const props = defineProps({
  userType: {
   type: String,
   required: true
  }
})

const strategies = {
  'user': UserBoard,
  'staff': StaffBoard
}
</script>

3. 策略模式在开发中的应用

在开发中很多时候会碰到Modal里只需要一两个输入框的场景,如果专门为了这个输入框去定义一整个表单的话,感觉是有点没必要的。常见的是使用if-else去判断输入框字段是否合法,那么可以使用策略模式,去定义一个useRules,在全局去进行使用。

typescript 复制代码
/**
 * ex:
 *  先添加需要验证的规则
 *  const ruleValidator = useRules();
 *  ruleValidator.addValidatorCache(phone,"isEmpty","请输入手机号");
 *  ruleValidator.addValidatorCache(phone,"isMobile",'请填写正确手机号格式');
 *  添加后验证: ruleValidator.check();
 * @returns {{addValidatorCache: addValidatorCache, check: (function(): null)}|{result: *, reason: *|string}}
 */
export function useRules() {
  const validatorCache = [];
  
  /**
   *
   * @param boolean {Boolean} - 验证结果
   * @param reason {String} - 报错原因
   * @returns {{result: {Boolean},reason?: {String}}}
   */
  const makeValidationResult = (boolean, reason) => {
   return {
    result: boolean,
    reason: boolean?reason:''
   }
  }
  
  const ruleStrategies = {
   /**
    *
    * @param refValue {Ref} - 验证值
    * @param reason {String} - 报错原因
    * @returns {{result: {Boolean},reason?: {String}}}
    */
   isEmpty(refValue, reason) {
    let value = refValue.value;
    return makeValidationResult(!value,reason);
   },
   
   /**
    *
    * @param refValue {Ref} - 验证值
    * @param maxLength {Number} - 最大长度
    * @param reason {String} - 报错原因
    * @returns {{result: {Boolean},reason?: {String}}}
    */
   isOverMaxLength(refValue, maxLength, reason) {
    let value = refValue.value;
    const boolean = value?.length > maxLength;
    return makeValidationResult(boolean,reason);
   },
   
   /**
    *
    * @param refValue {Ref} - 验证值
    * @param reason {String} - 报错原因
    * @returns {{result: {Boolean},reason?: {String}}}
    */
   isMobile(refValue, reason) {
    let value = refValue.value;
    const boolean = !/^1[34578]\d{9}$/.test(value);
    return makeValidationResult(boolean,reason);
   }
  }
  
  /**
   *
   * @param value {Ref} - 验证值
   * @param rule {String} - 形如 "isOverMaxLength:3"
   * @param errorMsg {String} - 报错消息
   */
  const addValidatorCache = (value, rule, errorMsg) => {
   const params = rule.split(':');
   let strategy = params.shift();
   params.unshift(value);
   params.push(errorMsg);
   validatorCache.push(() => {
    //传params到ruleStrategies[strategy]函数中
    return ruleStrategies[strategy].apply(null, params);
   })
  }
  
  /**
   * 检查已添加规则
   * @returns {{result: {Boolean},reason?: {String}}}
   */
  const check = () => {
   let validator = null;
   validatorCache.some(validatorFunc => {
    validator = validatorFunc();
    if(validator.result){
     $message.warning({
      content: validator.reason
     })
     return true;
    }
   })
   return validator;
  }
  return { addValidatorCache,check };
}
相关推荐
donecoding1 小时前
一个 sudo 引发的血案:npm 全局包权限错乱彻底修复
前端·node.js·前端工程化
风骏时光牛马1 小时前
Raku正则匹配与数据批量处理实操案例
前端
nbwenren1 小时前
2026实测:Gemini 3 镜像站视觉能力实践——拍照原型图,一键生成 HTML+CSS 代码
前端·css·html
Lee川1 小时前
Prisma 实战指南:像搭积木一样设计古诗词数据库
前端·数据库·后端
jinanwuhuaguo1 小时前
(第二十九篇)OpenClaw 实时与具身的跃迁——从异步孤岛到数字世界的“原住民”
前端·网络·人工智能·重构·openclaw
广州华水科技1 小时前
深度测评2026年单北斗GNSS位移监测系统推荐,与高口碑变形监测设备一同引领行业新风尚
前端
Alice-YUE2 小时前
【js高频八股】防抖与节流
开发语言·前端·javascript·笔记·学习·ecmascript
是上好佳佳佳呀3 小时前
【前端(十一)】JavaScript 语法基础笔记(多语言对比)
前端·javascript·笔记
CDN3604 小时前
排查实录:网站偶发502/504错误?360CDN回源超时配置与日志分析技巧
前端·数据库