1. 什么是策略模式
策略模式的定义是:定义一系列的算法,把它们一个个封装起来,并且使它们可以互相替换。
它最主要的目的是将算法与环境区分开,让算法与环境之间解耦。
策略模式由两部分组成:
- 第一部分是策略类
strategy
,策略类负责封装多个算法 - 第二部分是环境类
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 };
}