内容简介:策略模式由两部分构成:一部分是封装不同策略的策略组,另一部分是 Context。通过组合和委托来让 Context 拥有执行策略的能力,从而实现易扩展、易理解,并且避免大量复制粘贴的工作。策略模式的典型应用场景是表单校验中,对于校验规则的封装。接下来通过两个例子简单了解下 JavaScript 中策略模式的使用:因为百度AI图像识别的接口类型不同,所需的参数格式也不尽相同。然而图像的压缩及上传、错误处理等部分是公用的。所以可以采用策略模式封装:
策略模式由两部分构成:一部分是封装不同策略的策略组,另一部分是 Context。通过组合和委托来让 Context 拥有执行策略的能力,从而实现易扩展、易理解,并且避免大量复制粘贴的工作。策略模式的典型应用场景是表单校验中,对于校验规则的封装。
接下来通过两个例子简单了解下 JavaScript 中策略模式的使用:
使用策略模式调用百度AI图像识别
因为百度AI图像识别的接口类型不同,所需的参数格式也不尽相同。然而图像的压缩及上传、错误处理等部分是公用的。所以可以采用策略模式封装:
定义策略组
通过定义策略组来封装不同的接口及其参数:比如身份证识别接口的 side
字段,自定义识别的 templateSign
字段,以及行驶证识别的接收参数为 poparamstData
。
/**
* 策略组
* IDCARD:身份证识别
* CUSTOMIZED:自定义识别
* VL:行驶证识别
*/
var strategies = {
IDCARD: function (base64) {
return {
path: 'idcard',
param: {
'side': 'front',
'base64': base64
}
};
},
CUSTOMIZED: function (base64) {
return {
path: 'customized',
param: {
'templateSign': '52cc2d402155xxxx',
'base64': base64
}
};
},
VL: function (base64) {
return {
path: 'vehicled',
poparamstData: {
'base64': base64
}
};
},
};
复制代码
定义 Context
var ImageReader = function () { };
/**
* 读取图像,调用接口,获取识别结果
*
* @param {*} type 待识别文件类型
* @param {*} base64 待识别文件 BASE64码
* @param {*} callBack 识别结果回调
*/
ImageReader.prototype.getOcrResult = function (type, base64, callBack) {
let fileSize = (base64.length / (1024 * 1024)).toFixed(2);
let compressedBase64 = '';
let image = new Image();
image.src = base64;
image.onload = function () {
/**
* 图片压缩处理及异常处理,代码略
*/
let postData = strategies[type](compressedBase64);
ajax(
host + postData.path, {
data: postData.param,
type: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
success: function (res) {
var data = JSON.parse(res);
// 暴露给 UI 层的统一的错误码
if (data.error_code !== undefined && data.error_code !== 0) {
var errorData = {
error: 1,
title: '错误 ' + data.error_code,
content: 'error message'
};
callBack(errorData);
} else {
callBack(data);
}
}
});
};
};
复制代码
调用方式
var imageReader = new ImageReader();
imageReader.getOcrResult('IDCARD', this.result.toString(), callback);
复制代码
策略模式封装 Vue Select 组件
某项目中多处用到了 element-ui 的 select 组件,其内在逻辑类似,都是初始化时获取下拉列表的数据源,然后在选中某一项时 dispatch 不同的 action。遂考虑使用策略模式封装。
Context
在本例中,组件向外部暴露一个 prop,调用方指定该 prop 从而加载不同的策略。那么定义 Context 如下:
<template>
<el-select v-model="selectedValue" placeholder="请选择" @change="optionChanged" size="mini" clearable>
<el-option v-for="item in options" :key="item.id" :label="item.name" :value="item.id">
</el-option>
</el-select>
</template>
复制代码
data() {
return {
selectedValue: undefined,
options: [],
action: "",
};
},
props: {
// 暴露给外部的 select-type
selectType: {
type: String
},
},
created() {
// 获取 options
this.valuation();
},
methods: {
optionChanged() {
this.$emit(this.action, this.selectedValue);
},
setOptions(option) {
this.$store.dispatch(this.action, option);
},
valuation() {
// 获取 options 数据
}
},
复制代码
外部通过如下方式调用组件:
<MySelect selectType="product"/> 复制代码
strategies
然后定义策略组:
let strategies = {
source: {
action: "sourceOption",
getOptions: function() {
// 拉取 options
}
},
product: {
action: "productOption",
getOptions: function() {
// 拉取 options
}
},
...
}
复制代码
异步
至此该组件的基本结构已经清晰,但还存在一个问题:组件加载时是异步拉取的 options, 而页面初始化的时候很可能 options 还没有返回,导致 select 的 options 仍为空。所以此处应该修改代码,同步获取 options:
// 策略组修改
source: {
action: "sourceOption",
getOptions: async function() {
// await 拉取 options
}
},
// 组件修改
methods: {
...
async valuation() {
...
}
}
复制代码
继续优化
但我们不是每次加载组件都需要拉取 options,如果这些 options 在其他组件或者页面也被使用到,那么可以考虑将其存入 vuex 中。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Python语言程序设计基础(第2版)
嵩天、礼欣、黄天羽 / 高等教育出版社 / 2017-2 / 39
本书提出了以理解和运用计算生态为目标的Python语言教学思想,不仅系统讲解了Python语言语法,同时介绍了从数据理解到图像处理的14个Python函数库,向初学Python语言的读者展示了全新的编程语言学习路径。 全书一共设计了25个非常具有现代感的实例,从绘制蟒蛇、理解天天向上的力量到机器学习、网络爬虫,从文本进度条、统计名著人物重要性到图像手绘效果、雷达图绘制,绝大多数实例为作者原创......一起来看看 《Python语言程序设计基础(第2版)》 这本书的介绍吧!