Javascript—策略模式

拿生活场景举例,放假回家,学生可以选择乘坐火车、高铁、飞机等方式,每一种回家方式就是一种策略。

拿编程场景举例,实现一个功能,可以有多种不同的算法,那每种算法就是一种策略,这些算法可以随意替换,开发者可以从中挑选任意的算法去实现这一功能。

  1. 概念

定义一系列的算法,把它们一个个封装起来, 并且使它们可相互替换

  1. 应用场景举例

来看一个可以应用策略模式的场景:表单验证(微信小程序)

这是管理端发布志愿活动的页面,针对该场景,需要进行对用户发布表单做验证,以下为最容易想到、最简单实现的方法

  postActivity: function () {
    if (this.data.eventName === '') {
      Toast.fail('活动标题未填');
      return
    }
    if (this.data.location === '') {
      Toast.fail('活动地点未填');
      return
    }
    if (this.data.pushLink === '') {
      Toast.fail('推送链接未填');
      return
    }
    if (this.data.sponsor === '') {
      Toast.fail('主办方未填');
      return
    }
    if (this.data.type === '') {
      Toast.fail('活动类型未填');
      return
    }
    if (this.data.startTime === '') {
      Toast.fail('报名时间未填');
      return
    }
    if (this.data.endTime === '') {
      Toast.fail('报名截止时间未填');
      return
    }
    //向后端发送请求代码省略
  },

以上代码实现功能没有任何问题,但是缺点也很明显:

1 if语句太多,占大量篇幅,且逻辑几乎相同,一模一样格式的代码,没必要出现很多次

2 如果后续,客户要求新增逻辑,加一些其他输入,还得在postActivity函数内部再改

3 整段代码无复用性,一个项目中涉及到表单提交会有多处,就会有多处表单验证,上述代码仅实现了该页面的需要,如果其它页面逻辑与其相同,还得再写一份一样格式的代码(俗称cv)

实现策略模式下表单验证:

step1

定义策略对象,封装一系列算法或者业务逻辑(演示就不放太多方法了,不然看着容易眼花)

const strategies = {
  isEmpty: function (value, message) {
    if (value.length === 0) {
      return message;
    }
  }
 };

step2

定义环境,环境用来将用户的请求指派给策略对象中的某一个(如果不理解这一部分,可以先看step3)

class formValidation {
  constructor() {
    //保存校验规则
    this.cache = [];
  }
  //用来添加校验规则的方法
  add(value, rule, message) {
    //用空函数将策略包装,推进cache中
    this.cache.push(function () {
      return strategies[rule](value, message);
    })
  }
  //用来启动校验的方法
  start() {
    let msg;
    this.cache.some(fn => {
      msg = fn();
      if (msg) {
        return true;
      }
    })
    this.cache = [];
    return msg;
  }
}

step3

使用,也就是用户的请求

  postActivity: function () {
    formValidation.add(this.data.eventName, 'isEmpty', '活动标题未填');
    formValidation.add(this.data.location, 'isEmpty', '活动地点未填');
    formValidation.add(this.data.pushLink, 'isEmpty', '推送链接未填');
    formValidation.add(this.data.sponsor, 'isEmpty', '主办方未填');
    formValidation.add(this.data.index, 'isEmpty', '活动类型未填');
    formValidation.add(this.data.startTime, 'isEmpty', '报名时间未填');
    formValidation.add(this.data.endTime, 'isEmpty', '报名截止时间未填');
    const errMsg = formValidation.start();
    if (errMsg) {
      Toast.fail(errMsg);
      return;
    }
   //向后端发送请求代码省略
  },

附完整代码

utils/form-validation.js
//定义策略
const strategies = {
  isEmpty: function (value, message) {
    if (value.length === 0) {
      return message;
    }
  }
};

//定义环境 
class formValidation {
  constructor() {
    //保存校验规则
    this.cache = [];
  }
  //用来添加校验规则的方法
  add(value, rule, message) {
    //用空函数将策略包装,推进cache中
    this.cache.push(function () {
      return strategies[rule](value, message);
    })
  }
  //用来启动校验的方法
  start() {
    let msg;
    this.cache.some(fn => {
      msg = fn();
      if (msg) {
        return true;
      }
    })
    this.cache = [];
    return msg;
  }
}

module.exports = {
  formValidation: new formValidation()
}
add-activity.js
import {
  formValidation
} from "../../utils/form-validation";
Page({
  data: {},
  postActivity: function () {
    formValidation.add(this.data.eventName, 'isEmpty', '活动标题未填');
    formValidation.add(this.data.location, 'isEmpty', '活动地点未填');
    formValidation.add(this.data.pushLink, 'isEmpty', '推送链接未填');
    formValidation.add(this.data.sponsor, 'isEmpty', '主办方未填');
    formValidation.add(this.data.index, 'isEmpty', '活动类型未填');
    formValidation.add(this.data.startTime, 'isEmpty', '报名时间未填');
    formValidation.add(this.data.endTime, 'isEmpty', '报名截止时间未填');
    const errMsg = formValidation.start();
    if (errMsg) {
      Toast.fail(errMsg);
      return;
    }
    //向后端发送请求代码省略
  }
})

以上仅实现了验证输入文本是否为空规则,如果业务有更多要求,可以继续在策略对象里添加其它方法。

结尾:

策略模式优点:

代码可复用在项目中其他地方,省去了很多的cv步骤;

支持开放——封闭原则,即当项目需求发生变动时,不修改项目原有的代码功能,而是扩展模块的功能,来实现新的需求;

利用了组合、委托、多态等技术和思想,有效避免了多重条件语句。

策略模式缺点:

要向使用的用户暴露策略类里面的多种策略。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值