一、策略模式定义:

定义一些列的算法/规则,将它们封装起来,使得它们可以互相替换/组合使用。其目的在于将算法/规则封装起来,将算法/规则的使用与实现分离出来。

通过策略模式,可以减少算法计算过程中大量的if-else分支,并提高复用性。

一个策略模式的程序至少由两部分组成,一个是一组策略类,策略类封装了具体算法,并负责具体的实现过程;第二个部分是环境类context,context接受客户的请求,随后将请求委托给具体的某一个策略类。context中需要有一个变量来保存对对象的引用。

二、java中的策略模式:

考虑以下应用场景,大部分公司都会根据绩效发放年终奖,假设说如果绩效为A的话,年终奖发放5倍月薪;如果绩效为B的话,年终奖发放4倍月薪。按照一般的思路,计算函数中可能包含如下的分支语句,if (绩效为A) else if(绩效为B){};如果新增了一个C绩效,则需要进入计算函数的内部进行修改,因此考虑将算法的实现与算法的使用相分离。

为了实现多态,需要定义对应的接口或者抽象类:

  1. package com.bobo.shejimoshi;
  2.  
  3. public abstract class Performance {
  4.  
  5. public abstract int calBonus(int salary);
  6.  
  7. }

绩效A类:

  1. package com.bobo.shejimoshi;
  2.  
  3. public class PerformanceA extends Performance{
  4.  
  5. @Override
  6. public int calBonus(int salary) {
  7. // TODO Auto-generated method stub
  8. return salary*;
  9. }
  10. }

绩效B类:

  1. package com.bobo.shejimoshi;
  2.  
  3. public class PerformanceB extends Performance{
  4.  
  5. @Override
  6. public int calBonus(int salary) {
  7. // TODO Auto-generated method stub
  8. return salary*;
  9. }
  10. }

实现context类:

  1. package com.bobo.shejimoshi;
  2.  
  3. public class Bonus {
  4. private Performance perfo;
  5. private int salary;
  6.  
  7. public void setPerfo(Performance perfo) {
  8. this.perfo = perfo;
  9. }
  10.  
  11. public void setSalary(int salary) {
  12. this.salary = salary;
  13. }
  14.  
  15. public int getBonus(int salary){
  16. return this.perfo.calBonus(salary);
  17. }
  18. }

调用方法如下:

  1. package com.bobo.shejimoshi;
  2.  
  3. public class Test {
  4.  
  5. public static void main(String[] args) {
  6. Bonus bonus = new Bonus();
  7. bonus.setPerfo(new PerformanceA());
  8. System.out.println(bonus.getBonus());//输出4000
  9.  
  10. bonus.setPerfo(new PerformanceB());
  11. System.out.println(bonus.getBonus());//输出5000
  12. }
  13.  
  14. }

三、javascript中的策略模式

在javascript中,函数也是对象,因此完全不必要使用策略类,将其直接定义为函数即可。对策略的引用可以像java中通过context类的一个属性来保存其引用,可以通过函数参数来进行传递。

  1. //策略模式
  2.  
  3. //策略实现
  4. var strategies={
  5. 'S':function(salary){
  6. return salary*;
  7. },
  8. 'A':function(salary){
  9. return salary*;
  10. },
  11. 'B':function(salary){
  12. return salary*;
  13. }
  14. };
  15.  
  16. //context实现
  17. var calBonus=function(leval,salary){
  18. return strategies[leval].call(this,salary);
  19. };
  20.  
  21. console.log(calBonus('S',));
  22. console.log(calBonus('A',));

三、案例

1)jquery中的动画类,其各种缓动动画,也是策略模式的具体实现;

2)如果认为策略模式就是用来封装算法的,那未免太狭隘了,事实上,广义的算法也可以是一系列的“业务规则”,只要这些业务规则指向的目标一致,就可以被替换,甚至可以被组合使用。如下面封装的一个表单验证插件。

  1. //使用策略模式来实现表单验证
  2. var strategies = {
  3. 'isNonEmpty': function(value, errorMsg) {
  4. if (value == '') {
  5. return errorMsg;
  6. }
  7. },
  8. 'minLength': function(value, length, errorMsg) {
  9. if (value.length < length) {
  10. return errorMsg;
  11. }
  12. },
  13. };
  14.  
  15. function Validate() {
  16. this.cache = [];
  17. }
  18. Validate.prototype.add = function(dom, rules) {
  19. var self = this;
  20. for (var i = ; i < rules.length; i++) {
  21. var curRule = rules[i];
  22. (function(curRule) {
  23. var argsAry = curRule['strategy'].split(':');
  24. var errorMsg = curRule['errorMsg'];
  25. self.cache.push(function() {
  26. var strategy = argsAry.shift();
  27. argsAry.unshift(dom.value);
  28. argsAry.push(errorMsg);
  29. return strategies[strategy].apply(dom, argsAry);
  30. });
  31. })(curRule);
  32. }
  33. };
  34. Validate.prototype.start = function() {
  35. for (var i = ; i < this.cache.length; i++) {
  36. var func = this.cache[i];
  37. var errorMsg = func();
  38. if (errorMsg) {
  39. return errorMsg;
  40. }
  41. }
  42. };
  43. var testForm = document.getElementById("testForm");
  44.  
  45. function validateForm() {
  46. var validate = new Validate();
  47. validate.add(testForm.username, [{ 'strategy': 'isNonEmpty', 'errorMsg': '该字段不能为空!' }]);
  48. validate.add(testForm.password, [{ 'strategy': 'minLength:3', 'errorMsg': '输入长度不能小于3' }]);
  49. console.log(validate.cache);
  50. var errorMsg = validate.start();
  51. return errorMsg;
  52. }
  53. testForm.onsubmit = function() {
  54. var errorMsg = validateForm();
  55. if (errorMsg) {
  56. console.log(errorMsg);
  57. return false;
  58. }
  59. };

如果采用《你不知道的javascript》中推崇的基于委托的写法,那么实现的代码如下:

  1. //基于委托的表单验证组件的实现
  2. //在编写组件之前,首先了解用户是如何使用组件的,总的来说,有两个API
  3. //.add(registerForm.password,[{strategy:'minLength:6',errorMsg:'长度不能小于6'},{strategy:'isNonEmpty',errorMsg:'输入不能为空'}],'长度不能小于6位');添加校验规则
  4. //.start()启动校验,返回错误信息
  5.  
  6. var strategies={
  7. isNonEmpty:function(value,errorMsg){
  8. console.log(arguments);
  9. if(value==''){
  10. return errorMsg;
  11. }
  12. },
  13. minLength:function(value,length,errorMsg){
  14. if(value.length<length){
  15. return errorMsg;
  16. }
  17. },
  18. isMobile:function(value,errorMsg){
  19. if(!/^[||][-]{}/.test(value)){
  20. return errorMsg;
  21. }
  22. }
  23. };
  24. var validator={
  25. //不是函数,内部不能定义变量
  26. //var cache=[],
  27. init:function(){
  28. this.cache=[];
  29. },
  30. add:function(elem,rules){
  31. var i,len,self=this;
  32. for(i=,len=rules.length;i<len;i++){
  33. (function(i){
  34. self.cache.push(function(){
  35. //这是个闭包
  36. var curRule=rules[i],
  37. strategyAry=curRule.strategy.split(':'),
  38. errorMsg=curRule.errorMsg,
  39. strategy=strategyAry.shift();
  40. strategyAry.push(errorMsg);
  41. strategyAry.unshift(elem.value);
  42. //console.log(strategy);
  43. return strategies[strategy].apply(elem,strategyAry);
  44. });
  45. })(i);
  46.  
  47. }
  48. },
  49. start:function(){
  50. var i,len,errorMsg;
  51. for(i=,len=this.cache.length;i<len;i++){
  52. if((errorMsg=this.cache[i]())!==undefined){
  53. return errorMsg;
  54. }
  55. }
  56. }
  57.  
  58. };
  59.  
  60. //测试
  61. var form=document.forms['login'];
  62.  
  63. var myValid=Object.create(validator);
  64. myValid.init();
  65. myValid.add(form.name,[{strategy:'isNonEmpty',errorMsg:'字段不能为空'},{strategy:'minLength:3',errorMsg:'长度不能小于3'}]);
  66. console.log(myValid.start());

javascript设计模式学习之五——策略模式的更多相关文章

  1. javascript设计模式--策略模式

    javascript策略模式总结 1.什么是策略模式? 策略模式的定义是:定义一系列的算法,把他们独立封装起来,并且可以相互替换. 例如我们需要写一段代码来计算员工的奖金.当绩效为a时,奖金为工资的5 ...

  2. JavaScript设计模式 Item 7 --策略模式Strategy

    1.策略模式的定义 何为策略?比如我们要去某个地方旅游,可以根据具体的实际情况来选择出行的线路. 如果没有时间但是不在乎钱,可以选择坐飞机. 如果没有钱,可以选择坐大巴或者火车. 如果再穷一点,可以选 ...

  3. javascript设计模式实践之策略模式--输入验证

    策略模式中的策略就是一种算法或者业务规则,将这些策略作为函数进行封装,并向外提供统一的调用执行. 先定义一个简单的输入表单: <!DOCTYPE html> <html> &l ...

  4. 设计模式学习之策略模式(Strategy,行为型模式)(13)

    转载地址:http://www.cnblogs.com/zhili/p/StragetyPattern.html 一.引言 本文要介绍的策略模式也就是对策略进行抽象,策略的意思就是方法,所以也就是对方 ...

  5. Java设计模式学习记录-策略模式

    策略模式 策略模式的定义是:定义了一系列的算法,把它们一个个的封装起来,并且使它们可相互替换,让算法可以独立于使用它的客户而变化. 设计原则是:把一个类中经常改变或者将来可能会经常改变的部分提取出来作 ...

  6. Java-马士兵设计模式学习笔记-策略模式-模拟 Comparator接口

    续上一篇  <Java 模拟 Comparable接口> 一.Teacher类及Student类的比较大小方式是不固定的,比如老师除了比较职称外,还可比较工龄大小,年龄大小等.则定义Com ...

  7. javascript设计模式学习之六——代理模式

    一.代理模式定义 代理模式的关键是:当客户不方便直接访问一个对象或者不满足需要的时候,提供一个替身对象来控制对这个对象的访问.代理模式需要和本体对外提供相同的接口,对用户来说是透明的.代理模式的种类有 ...

  8. javascript设计模式学习之七——迭代器模式

    一.迭代器模式定义 迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素,并且不需要暴露该对象的内部表示. 在当前大部分语言中,都已经内置了迭代器模式.迭代器有内部迭代器和外部迭代器之分,一般现有语 ...

  9. Java-马士兵设计模式学习笔记-策略模式-模拟Comparable接口

    一.情况 1.目标:要在专门用于排序数据的DataSorter.java中实现对所有A类,B类,C类,D类等等的排序 2.初步想法:DataSorter.java的代码如下 public class ...

随机推荐

  1. MySQL数据库安装,配置My.ini文件

    最近在做项目开发时用到了MySql数据库,在看了一些有关MySql的文章后,很快就上手使用了.在使用的过程中还是出现了一些问题,因为使用的是绿色免安装版的MySql所以在配置的时候出现了一些问题,该篇 ...

  2. cursor:pointer

    .cursor_hand{ cursor:pointer; }

  3. JAVA分支语句例题

    1.输入年份判断是闰年还是平年? System.out.println("请输入年份:"); Scanner sc=new Scanner(System.in); String s ...

  4. Myeclipse配置 项目编码格式

    修改MyEclipse 工作空间的编码 修改之后,在该工作空间下创建的任何项目,编码都是UTF-8,既,该项目下所有文件都是utf-8 格式,工作空间影响项目,项目影响文件 General --> ...

  5. MyEclipse8.5 以debug模式启动tomcat6.0服务器 报错cannot connect to vm。

    打开MyEclipse8.5 想以debug模式启动tomcat6.0服务器,报  a configuration error occurred during startup.please verif ...

  6. 蓝牙4.0的LM层说明

    1.概念 The Link Manager Protocol (LMP) is used to control and negotiate all aspects of the operation o ...

  7. hiveserver2以及beeline客户端的使用

    一:开启服务 1.启动前端的hiveserver2 按住ctrl+c就可以结束这个服务. 2.怎么知道已经开启的服务 如果进程在后台,可以查出来,kill这些进程. 3.后端开启服务 二:beelin ...

  8. zepto源码--isEmptyObject,isNumeric,inArray,trim--学习笔记

    1.isEmptyObject,判断对象是否为空对象的函数 定义变量name,遍历传入对象的属性name,如果存在任何属性,则返回false,判定传入的参数为非空对象,否则即为空对象. 2.isNum ...

  9. Excel Sheet Column Number || leetcode

    很简单的26进制问题 int titleToNumber(char* s) { int sum=0,temp; char *p=s; while(*p!='\0'){ sum=sum*26+(*p-' ...

  10. Four Operations---hdu5938(暴力)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5938 题意:给一个不超过20位并且大于2位的数字字符串(只包含1-9)然后找到适当的位置依次放入&qu ...