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 };
}
相关推荐
foundbug9991 小时前
Modbus协议C语言实现(易于移植版本)
java·c语言·前端
Luna-player1 小时前
在前端中list.map的用法
前端·数据结构·list
用户47949283569151 小时前
面试官问 React Fiber,这一篇文章就够了
前端·javascript·react.js
LYFlied1 小时前
【一句话概述】Webpack、Vite、Rollup 核心区别
前端·webpack·node.js·rollup·vite·打包·一句话概述
reddingtons1 小时前
PS 参考图像:线稿上色太慢?AI 3秒“喂”出精细厚涂
前端·人工智能·游戏·ui·aigc·游戏策划·游戏美术
一水鉴天2 小时前
整体设计 定稿 之23+ dashboard.html 增加三层次动态记录体系仪表盘 之2 程序 (Q199 之2) (codebuddy)
开发语言·前端·javascript
刘发财2 小时前
前端一行代码生成数千页PDF,dompdf.js新增分页功能
前端·typescript·开源
_请输入用户名2 小时前
Vue 3 源码项目结构详解
前端·vue.js
少卿2 小时前
Next.js 国际化实现方案详解
前端·next.js
掘金挖土2 小时前
手摸手快速搭建 Vue3 + ElementPlus 后台管理系统模板,使用 JavaScript
前端·javascript