javascript设计模式学习之五——策略模式
一、策略模式定义:
定义一些列的算法/规则,将它们封装起来,使得它们可以互相替换/组合使用。其目的在于将算法/规则封装起来,将算法/规则的使用与实现分离出来。
通过策略模式,可以减少算法计算过程中大量的if-else分支,并提高复用性。
一个策略模式的程序至少由两部分组成,一个是一组策略类,策略类封装了具体算法,并负责具体的实现过程;第二个部分是环境类context,context接受客户的请求,随后将请求委托给具体的某一个策略类。context中需要有一个变量来保存对对象的引用。
二、java中的策略模式:
考虑以下应用场景,大部分公司都会根据绩效发放年终奖,假设说如果绩效为A的话,年终奖发放5倍月薪;如果绩效为B的话,年终奖发放4倍月薪。按照一般的思路,计算函数中可能包含如下的分支语句,if (绩效为A) else if(绩效为B){};如果新增了一个C绩效,则需要进入计算函数的内部进行修改,因此考虑将算法的实现与算法的使用相分离。
为了实现多态,需要定义对应的接口或者抽象类:
package com.bobo.shejimoshi;
public abstract class Performance {
public abstract int calBonus(int salary);
}
绩效A类:
package com.bobo.shejimoshi;
public class PerformanceA extends Performance{
@Override
public int calBonus(int salary) {
// TODO Auto-generated method stub
return salary*;
}
}
绩效B类:
package com.bobo.shejimoshi;
public class PerformanceB extends Performance{
@Override
public int calBonus(int salary) {
// TODO Auto-generated method stub
return salary*;
}
}
实现context类:
package com.bobo.shejimoshi;
public class Bonus {
private Performance perfo;
private int salary;
public void setPerfo(Performance perfo) {
this.perfo = perfo;
}
public void setSalary(int salary) {
this.salary = salary;
}
public int getBonus(int salary){
return this.perfo.calBonus(salary);
}
}
调用方法如下:
package com.bobo.shejimoshi;
public class Test {
public static void main(String[] args) {
Bonus bonus = new Bonus();
bonus.setPerfo(new PerformanceA());
System.out.println(bonus.getBonus());//输出4000
bonus.setPerfo(new PerformanceB());
System.out.println(bonus.getBonus());//输出5000
}
}
三、javascript中的策略模式
在javascript中,函数也是对象,因此完全不必要使用策略类,将其直接定义为函数即可。对策略的引用可以像java中通过context类的一个属性来保存其引用,可以通过函数参数来进行传递。
//策略模式
//策略实现
var strategies={
'S':function(salary){
return salary*;
},
'A':function(salary){
return salary*;
},
'B':function(salary){
return salary*;
}
};
//context实现
var calBonus=function(leval,salary){
return strategies[leval].call(this,salary);
};
console.log(calBonus('S',));
console.log(calBonus('A',));
三、案例
1)jquery中的动画类,其各种缓动动画,也是策略模式的具体实现;
2)如果认为策略模式就是用来封装算法的,那未免太狭隘了,事实上,广义的算法也可以是一系列的“业务规则”,只要这些业务规则指向的目标一致,就可以被替换,甚至可以被组合使用。如下面封装的一个表单验证插件。
//使用策略模式来实现表单验证
var strategies = {
'isNonEmpty': function(value, errorMsg) {
if (value == '') {
return errorMsg;
}
},
'minLength': function(value, length, errorMsg) {
if (value.length < length) {
return errorMsg;
}
},
}; function Validate() {
this.cache = [];
}
Validate.prototype.add = function(dom, rules) {
var self = this;
for (var i = ; i < rules.length; i++) {
var curRule = rules[i];
(function(curRule) {
var argsAry = curRule['strategy'].split(':');
var errorMsg = curRule['errorMsg'];
self.cache.push(function() {
var strategy = argsAry.shift();
argsAry.unshift(dom.value);
argsAry.push(errorMsg);
return strategies[strategy].apply(dom, argsAry);
});
})(curRule);
}
};
Validate.prototype.start = function() {
for (var i = ; i < this.cache.length; i++) {
var func = this.cache[i];
var errorMsg = func();
if (errorMsg) {
return errorMsg;
}
}
};
var testForm = document.getElementById("testForm"); function validateForm() {
var validate = new Validate();
validate.add(testForm.username, [{ 'strategy': 'isNonEmpty', 'errorMsg': '该字段不能为空!' }]);
validate.add(testForm.password, [{ 'strategy': 'minLength:3', 'errorMsg': '输入长度不能小于3' }]);
console.log(validate.cache);
var errorMsg = validate.start();
return errorMsg;
}
testForm.onsubmit = function() {
var errorMsg = validateForm();
if (errorMsg) {
console.log(errorMsg);
return false;
}
};
如果采用《你不知道的javascript》中推崇的基于委托的写法,那么实现的代码如下:
//基于委托的表单验证组件的实现
//在编写组件之前,首先了解用户是如何使用组件的,总的来说,有两个API
//.add(registerForm.password,[{strategy:'minLength:6',errorMsg:'长度不能小于6'},{strategy:'isNonEmpty',errorMsg:'输入不能为空'}],'长度不能小于6位');添加校验规则
//.start()启动校验,返回错误信息 var strategies={
isNonEmpty:function(value,errorMsg){
console.log(arguments);
if(value==''){
return errorMsg;
}
},
minLength:function(value,length,errorMsg){
if(value.length<length){
return errorMsg;
}
},
isMobile:function(value,errorMsg){
if(!/^[||][-]{}/.test(value)){
return errorMsg;
}
}
};
var validator={
//不是函数,内部不能定义变量
//var cache=[],
init:function(){
this.cache=[];
},
add:function(elem,rules){
var i,len,self=this;
for(i=,len=rules.length;i<len;i++){
(function(i){
self.cache.push(function(){
//这是个闭包
var curRule=rules[i],
strategyAry=curRule.strategy.split(':'),
errorMsg=curRule.errorMsg,
strategy=strategyAry.shift();
strategyAry.push(errorMsg);
strategyAry.unshift(elem.value);
//console.log(strategy);
return strategies[strategy].apply(elem,strategyAry);
});
})(i); }
},
start:function(){
var i,len,errorMsg;
for(i=,len=this.cache.length;i<len;i++){
if((errorMsg=this.cache[i]())!==undefined){
return errorMsg;
}
}
} }; //测试
var form=document.forms['login']; var myValid=Object.create(validator);
myValid.init();
myValid.add(form.name,[{strategy:'isNonEmpty',errorMsg:'字段不能为空'},{strategy:'minLength:3',errorMsg:'长度不能小于3'}]);
console.log(myValid.start());
javascript设计模式学习之五——策略模式的更多相关文章
- javascript设计模式--策略模式
javascript策略模式总结 1.什么是策略模式? 策略模式的定义是:定义一系列的算法,把他们独立封装起来,并且可以相互替换. 例如我们需要写一段代码来计算员工的奖金.当绩效为a时,奖金为工资的5 ...
- JavaScript设计模式 Item 7 --策略模式Strategy
1.策略模式的定义 何为策略?比如我们要去某个地方旅游,可以根据具体的实际情况来选择出行的线路. 如果没有时间但是不在乎钱,可以选择坐飞机. 如果没有钱,可以选择坐大巴或者火车. 如果再穷一点,可以选 ...
- javascript设计模式实践之策略模式--输入验证
策略模式中的策略就是一种算法或者业务规则,将这些策略作为函数进行封装,并向外提供统一的调用执行. 先定义一个简单的输入表单: <!DOCTYPE html> <html> &l ...
- 设计模式学习之策略模式(Strategy,行为型模式)(13)
转载地址:http://www.cnblogs.com/zhili/p/StragetyPattern.html 一.引言 本文要介绍的策略模式也就是对策略进行抽象,策略的意思就是方法,所以也就是对方 ...
- Java设计模式学习记录-策略模式
策略模式 策略模式的定义是:定义了一系列的算法,把它们一个个的封装起来,并且使它们可相互替换,让算法可以独立于使用它的客户而变化. 设计原则是:把一个类中经常改变或者将来可能会经常改变的部分提取出来作 ...
- Java-马士兵设计模式学习笔记-策略模式-模拟 Comparator接口
续上一篇 <Java 模拟 Comparable接口> 一.Teacher类及Student类的比较大小方式是不固定的,比如老师除了比较职称外,还可比较工龄大小,年龄大小等.则定义Com ...
- javascript设计模式学习之六——代理模式
一.代理模式定义 代理模式的关键是:当客户不方便直接访问一个对象或者不满足需要的时候,提供一个替身对象来控制对这个对象的访问.代理模式需要和本体对外提供相同的接口,对用户来说是透明的.代理模式的种类有 ...
- javascript设计模式学习之七——迭代器模式
一.迭代器模式定义 迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,并且不需要暴露该对象的内部表示. 在当前大部分语言中,都已经内置了迭代器模式.迭代器有内部迭代器和外部迭代器之分,一般现有语 ...
- Java-马士兵设计模式学习笔记-策略模式-模拟Comparable接口
一.情况 1.目标:要在专门用于排序数据的DataSorter.java中实现对所有A类,B类,C类,D类等等的排序 2.初步想法:DataSorter.java的代码如下 public class ...
随机推荐
- angular+selecte2(angular ng-repeat渲染)
一.页面代码 <select id="sponsorId" select2 ng-model="sponsorSelectedObj" ng-change ...
- VMware 虚拟机使用 NAT 方式联网
选择要设置的虚拟主机: 点击右键,选择 “属性”,查看 “网络适配器”: 此时选择的连接方式是 “Host-only”,在 Host-only 模式中,所有的虚拟系统是可以相互通信的,但虚拟系统和真实 ...
- Nginx 笔记与总结(3)配置虚拟主机
Nginx 重启的另外一种方式,相当于 kill -HUP `cat /usr/local/nginx/logs/nginx.pid`: /usr/local/nginx/sbin/nginx -s ...
- 微信公众账号开发教程(三) 实例入门:机器人(附源码) ——转自http://www.cnblogs.com/yank/p/3409308.html
一.功能介绍 通过微信公众平台实现在线客服机器人功能.主要的功能包括:简单对话.查询天气等服务. 这里只是提供比较简单的功能,重在通过此实例来说明公众平台的具体研发过程.只是一个简单DEMO,如果需要 ...
- AES加密时抛出 Illegal key size or default parameters
使用AES加密时,当密钥大于128时,代码会抛出java.security.InvalidKeyException: Illegal key size or default parameters Il ...
- sql 语句查询练习题
1. 查询Student表中的所有记录的Sname.Ssex和Class列. select sname,ssex,class from student 2. 查询教师所有的单位即不重复的Depart列 ...
- VC 中 UpdateData() 函数的使用
UpdateData(FALSE)与UpdateData(TRUE)是相反的过程 UpdateData(FALSE)是把程序中改变的值更新到控件中去 UpdateData(TRUE)是把在控件中输入的 ...
- SHELL 八大扩展
最近在梳理bash知识的的过程中,有幸阅读了man bash文档,一时间犹如醍醐灌顶一般,很多当初不明白的地方都豁然开朗,现在就其中的一点做一分享,同时也为man bash做一下广告,当你面对bash ...
- 回调的代理(delegate)实现
1.CoreManage.h #import <Foundation/Foundation.h> @protocol SampleProtocol; //声明核心类的属性和方法 @inte ...
- 一种swift编码风格指南(供参考,by linkedin)
http://www.cocoachina.com/swift/20160701/16894.html