介绍

策略模式定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化不会影响到使用算法的客户。

正文

在理解策略模式之前,我们先来一个例子,一般情况下,如果我们要做数据合法性验证,很多时候都是按照swith语句来判断,但是这就带来几个问题,首先如果增加需求的话,我们还要再次修改这段代码以增加逻辑,而且在进行单元测试的时候也会越来越复杂,代码如下:

        validator = {            validate: function (value, type) {switch (type) {case 'isNonEmpty ':                        {return true; // NonEmpty 验证结果                        }case 'isNumber ':                        {return true; // Number 验证结果                            break;                        }case 'isAlphaNum ':                        {return true; // AlphaNum 验证结果                        }default:                        {return true;                        }                }            }        };//  测试        alert(validator.validate("123", "isNonEmpty"));

那如何来避免上述代码中的问题呢,根据策略模式,我们可以将相同的工作代码单独封装成不同的类,然后通过统一的策略处理类来处理,OK,我们先来定义策略处理类,代码如下:

var validator = {

// 所有可以的验证规则处理类存放的地方,后面会单独定义    types: {},

// 验证类型所对应的错误消息    messages: [],

// 当然需要使用的验证类型    config: {},

// 暴露的公开验证方法    // 传入的参数是 key => value对    validate: function (data) {

var i, msg, type, checker, result_ok;

// 清空所有的错误信息        this.messages = [];

for (i in data) {if (data.hasOwnProperty(i)) {

                type = this.config[i];  // 根据key查询是否有存在的验证规则                checker = this.types[type]; // 获取验证规则的验证类

if (!type) {continue; // 如果验证规则不存在,则不处理                }if (!checker) { // 如果验证规则类不存在,抛出异常                    throw {                        name: "ValidationError",                        message: "No handler to validate type " + type                    };                }

                result_ok = checker.validate(data[i]); // 使用查到到的单个验证类进行验证                if (!result_ok) {                    msg = "Invalid value for *" + i + "*, " + checker.instructions;this.messages.push(msg);                }            }        }return this.hasErrors();    },

// helper    hasErrors: function () {return this.messages.length !== 0;    }};

然后剩下的工作,就是定义types里存放的各种验证类了,我们这里只举几个例子:

// 验证给定的值是否不为空validator.types.isNonEmpty = {    validate: function (value) {return value !== "";    },    instructions: "传入的值不能为空"};

// 验证给定的值是否是数字validator.types.isNumber = {    validate: function (value) {return !isNaN(value);    },    instructions: "传入的值只能是合法的数字,例如:1, 3.14 or 2010"};

// 验证给定的值是否只是字母或数字validator.types.isAlphaNum = {    validate: function (value) {return !/[^a-z0-9]/i.test(value);    },    instructions: "传入的值只能保护字母和数字,不能包含特殊字符"};

使用的时候,我们首先要定义需要验证的数据集合,然后还需要定义每种数据需要验证的规则类型,代码如下:

var data = {    first_name: "Tom",    last_name: "Xu",    age: "unknown",    username: "TomXu"};

validator.config = {    first_name: 'isNonEmpty',    age: 'isNumber',    username: 'isAlphaNum'};

最后,获取验证结果的代码就简单了:

validator.validate(data);

if (validator.hasErrors()) {    console.log(validator.messages.join("\n"));}

总结

策略模式定义了一系列算法,从概念上来说,所有的这些算法都是做相同的事情,只是实现不同,他可以以相同的方式调用所有的方法,减少了各种算法类与使用算法类之间的耦合。

从另外一个层面上来说,单独定义算法类,也方便了单元测试,因为可以通过自己的算法进行单独测试。

实践中,不仅可以封装算法,也可以用来封装几乎任何类型的规则,是要在分析过程中需要在不同时间应用不同的业务规则,就可以考虑是要策略模式来处理各种变化。

同步与推荐

本文已同步至目录索引:深入理解JavaScript系列

深入理解JavaScript系列文章,包括了原创,翻译,转载等各类型的文章,如果对你有用,请推荐支持一把,给大叔写作的动力。

转载于:https://www.cnblogs.com/TomXu/archive/2012/03/05/2358552.html

深入理解JavaScript系列(33):设计模式之策略模式相关推荐

  1. 橘子学设计模式之策略模式

    策略模式 1.简介 俗话说:条条大路通罗马.在很多情况下,实现某个目标的途径不止一条,例如我们在外出 旅游时可以选择多种不同的出行方式,如骑自行车.坐汽车.坐火车或者坐飞机,可根据实 际情况(目的地. ...

  2. 设计模式之策略模式详解

    设计模式之策略模式详解 概述 先看下面的图片,我们去旅游选择出行模式有很多种,可以骑自行车.可以坐汽车.可以坐火车.可以坐飞机. 作为一个程序猿,开发需要选择一款开发工具,当然可以进行代码开发的工具有 ...

  3. 深入理解JavaScript系列(33):设计模式之策略模式(转)

    介绍 策略模式定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化不会影响到使用算法的客户. 正文 在理解策略模式之前,我们先来一个例子,一般情况下,如果我们要做数据合法性验证,很 ...

  4. 深入理解JavaScript系列(27):设计模式之建造者模式

    介绍 在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成:由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一 ...

  5. 深入理解JavaScript系列(32):设计模式之观察者模式

    介绍 观察者模式又叫发布订阅模式(Publish/Subscribe),它定义了一种一对多的关系,让多个观察者对象同时监听某一个主题对象,这个主题对象的状态发生变化时就会通知所有的观察者对象,使得它们 ...

  6. 深入理解JavaScript系列——汤姆大叔

    原文地址 深入理解JavaScript系列文章,包括了原创,翻译,转载,整理等各类型文章,如果对你有用,请推荐支持一把,给大叔写作的动力. 深入理解JavaScript系列(1):编写高质量JavaS ...

  7. 汤姆大叔深入理解JavaScript系列

    深入理解JavaScript系列文章,包括了原创,翻译,转载,整理等各类型文章,如果对你有用,请推荐支持一把,给大叔写作的动力. 深入理解JavaScript系列(1):编写高质量JavaScript ...

  8. [转载]深入理解JavaScript系列 --汤姆大叔

    深入理解JavaScript系列文章,包括了原创,翻译,转载,整理等各类型文章,如果对你有用,请推荐支持一把,给大叔写作的动力. 深入理解JavaScript系列(1):编写高质量JavaScript ...

  9. 深入理解JavaScript系列(转自汤姆大叔)

    深入理解JavaScript系列(转自汤姆大叔) 深入理解JavaScript系列文章,包括了原创,翻译,转载,整理等各类型文章,如果对你有用,请推荐支持一把,给大叔写作的动力. 深入理解JavaSc ...

最新文章

  1. 二十万字!耗时90天
  2. flash cs4 java运行时_加载外部数据时Flash CS4 IDE内部缓存
  3. java伪装反序列化字节流_java对象序列化流和反序列化流
  4. java.util中,util是什么意思
  5. installshield安装文件的制作小技巧--附加数据库
  6. linux 监听日志_Linux系统取证概述
  7. numpy.tile作用,语法,参数分析以及举例
  8. Pandas DataFrame 取消科学计数法打印
  9. Java开发者值得关注的十个技术博客
  10. windows 下安装图片标注软件 labelling和出错解决
  11. 【Review】数据结构线性表,数组算法(串模式匹配克鲁德、螺旋矩阵四墙)
  12. 教小师妹学多线程,看完我写的例子,脸红成那样!
  13. VerilogHDL正弦信号发生器
  14. 三相无刷直流电机的控制设计(一)基本硬件电路设计
  15. java酒店管理系统小型项目
  16. 苹果5港行和大陆行货的区别
  17. 浅谈量子量化股票交易的基本原理
  18. 百度竞价推广的真正意义是什么?
  19. android游戏开发原理及关键技术
  20. 网易运营微专业_运营基础

热门文章

  1. 学习手机游戏原画设计需要多长时间?难学吗?
  2. 零基础学Python-爬虫-1、网络请求Requests【网络操作理论基础与实践·请认真看看理论,理论基础决定后期高度】
  3. Toad for Oracle工具的使用(二)
  4. Oracle 中文分词CHINESE_VGRAM_LEXER与CHINESE_LEXER比较
  5. 用pip命令把python包安装到指定目录
  6. 重磅开源 KSQL:用于 Apache Kafka 的流数据 SQL 引擎 2017.8.29
  7. VS2017 下载离线MSDN文档
  8. css : 使用浮动实现左右各放一个元素时很容易犯的错误
  9. bzoj 1997: [Hnoi2010]Planar
  10. ef AddDays报错