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 };
}
相关推荐
Setsuna_F_Seiei9 小时前
前端转型 Agent 开发 06 之 Agent Memory 记忆系统(让 Agent 更智能,更懂你)
前端·agent·ai编程
zhangzeyuaaa10 小时前
Ruby 多线程、GVL(GIL)与 Mutex 完全指南
开发语言·前端·ruby
默_笙10 小时前
🌊 向量库和 ES 都查不出"关系",我只好给奶茶建了一张人脉网
前端·javascript
优选资讯10 小时前
标签打印软件怎么对接 Excel 数据
前端·excel
一个风轻云淡11 小时前
GCC 和 GDB命令简单解读
java·linux·前端
u01110267512 小时前
图片处理接口如何统一错误信息 前端提示与后端错误码设计
前端·状态模式
福兮说12 小时前
浏览器里把 iPhone 的 HEIC 转成 JPG:Chrome 解不开、转完大了七成、拍摄时间全丢,六个坑实测
前端·javascript·图像处理·chrome·ios·iphone·heic
libokaifa12 小时前
把语音模型塞进手机:sherpa-onnx 在 Android 上的 ASR / TTS
前端
deli00713 小时前
DLA 枝晶生长实测:5000 个粒子集体停摆之后,分形维数收敛到 1.70
前端
IT_陈寒13 小时前
Redis卡顿的锅,这次真不是大key的错
前端·人工智能·后端