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 };
}
相关推荐
kyriewen12 小时前
别再 console.log 了:5 个 Chrome DevTools 调试技巧,用过就回不去了
前端·javascript·面试
IT_陈寒13 小时前
Python搞不定字符串编码?这破玩意坑我两小时!
前端·人工智能·后端
DigitalOcean15 小时前
Laravel 开发者已在 DigitalOcean 上开通超过 10 万台服务器
前端·laravel
星始流年15 小时前
从 Tool 到 Skill——基于 LangChain 的服务端Skill实现
前端·langchain·agent
李惟15 小时前
开源本地通信库,纯客户端 RPC,像聊天一样通信
前端
YAwu1115 小时前
深入解析 React 炫彩鼠标跟随标题组件:从坐标定位到动画性能
前端·react.js
GuWenyue15 小时前
排序效率低?5分钟吃透快速排序,性能飙升至O(nlogn)
前端·javascript·面试
OpenTiny社区15 小时前
🎨 看完 GenUI SDK 源码我悟了!
前端·vue.js·github
叁两15 小时前
前端转型AI Agent该如何学习?(前置篇)
前端·人工智能·node.js
何时梦醒15 小时前
深入理解递归与快速排序 —— 从基础入门到手写实现
前端·javascript