`
iwebcode
  • 浏览: 2007920 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

JS实现策略模式

 
阅读更多
  作者:zhanhailiang 日期:2012-10-24

基本概念介绍

策略模式支持你在运行时选择算法。代码的客户端可以使用同一个接口来工作。但是它却根据客户正在试图执行任务的上下文,从多个算法中选择用于处理特定任务的算法。

使用策略模式的其中一个例子是解决表单验证问题。可以创建一个具有validate()方法的验证器(validator)对象。无论表单的具体类型是什么,该方法都将会被调用,并且总是返回相同的结果,一个未经验证的数据列表以及任意的错误消息。

但是根据具体的表单形式及待验证的数据,验证器的客户端可以选择不同类型的检查方法,验证器将选择最佳的策略以处理任务,并将具体的数据验证委托给适当的算法。

数据验证示例

假设有以下数据块,它可能来自于网页上的一个表单,而你需要验证它是否有效:

var data = {
    first_name : "Super",
    last_name : "Man",
    age : "unknown",
    username : "o_0"
};

在这个具体的例子中,为使验证器知道什么 是最好的策略,首先需要配置该验证器,并且设置认为是有效的且可接受的规则。

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

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

接下来实现validator。首先实现用于检查的可用算法。

validator.types.isNonEmpty = {
    validate : function(value) {
        return value !== '';
    },
    instructions : "the value cannot be empty."
};

validator.types.isNumber = {
    validate : function(value) {
        return !isNaN(value);
    },
    instructions : "the value can only be a valid number, e.g. 1, 3.14 or 2010."
};

validator.types.isAlphaNum = {
    validate : function(value) {
        return !/[^a-z0-9]/i.test(value);
    },
    instructions : "the value can only contain characters and numbers, no special symbols."
};

最后,核心的validator对象如下所示:

var validator = {
    // 所有可用的检查 
    types : {},

    // 在当前验证会话中的错误信息
    messages : [],

    // 当前验证配置名称:验证类型
    config : {},

    // 接口方法 `data`为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];
                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();
    },

    // 帮助函数
    hasErrors : function() {
        return this.messages.length !== 0;
    }
};

完整代码:

var validator = {
    // 所有可用的检查 
    types : {},

    // 在当前验证会话中的错误信息
    messages : [],

    // 当前验证配置名称:验证类型
    config : {},

    // 接口方法 `data`为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];
                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();
    },

    // 帮助函数
    hasErrors : function() {
        return this.messages.length !== 0;
    }
};

validator.types.isNonEmpty = {
    validate : function(value) {
        return value !== '';
    },
    instructions : "the value cannot be empty."
};

validator.types.isNumber = {
    validate : function(value) {
        return !isNaN(value);
    },
    instructions : "the value can only be a valid number, e.g. 1, 3.14 or 2010."
};

validator.types.isAlphaNum = {
    validate : function(value) {
        return !/[^a-z0-9]/i.test(value);
    },
    instructions : "the value can only contain characters and numbers, no special symbols."
};

var data = {
    first_name : "Super",
    last_name : "Man",
    age : "unknown",
    username : "o_0"
};

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

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

以上validator对象是通用的,增强validator对象的方法是添加更多的类型检查。若在多个页面中使用它,很快就会有一个优良的特定检查集合,故以后针对每个新的用例,所需做的就是配置该验证器并运行validate()方法。

分享到:
评论

相关推荐

    js代码-设计模式之策略模式--根据成绩等级计算最终得分

    js代码-设计模式之策略模式--根据成绩等级计算最终得分

    JavaScript设计模式之策略模式实现原理详解

    主要介绍了JavaScript设计模式之策略模式实现原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

    JavaScript模式中文[pdf] 百度云

    第1章 简介 ... 策略模式  外观模式  代理模式  中介者模式  观察者模式  小结  第8章 DOM和浏览器模式  关注分离  DOM脚本  事件  长期运行脚本  远程脚本  配置JavaScript  载入策略

    javascript设计模式 – 策略模式原理与用法实例分析

    本文实例讲述了javascript设计模式 – 策略模式原理与用法。分享给大家供大家参考,具体如下: 介绍:策略模式中可以定义一些独立的类来封装不同的算法,每一个类封装一种具体的算法。在这里,每一种算法的封装都...

    详解JavaScript的策略模式编程

    为了实现策略模式,通常有两个参与者: 该策略的对象,封装了算法。 客户端(上下文)对象,以即插即用的方式能使用任何策略。 这里介绍了我在Javascrip里,怎样使用策略模式,在混乱无序的环境中怎样使用它将库拆成

    JS设计模式之策略模式概念与用法分析

    主要介绍了JS设计模式之策略模式概念与用法,简单分析了策略模式的基本概念、原理并结合实例形式分析了javascript实现与使用策略模式的相关操作技巧,需要的朋友可以参考下

    JavaScript模式 斯托扬·斯特凡洛夫 著

    前言 第1章 简介 模式 JavaScript:基本概念 ...策略模式 外观模式 代理模式 中介者模式 观察者模式 小结 第8章 DOM和浏览器模式 关注分离 DOM脚本 事件 长期运行脚本 远程脚本 酉己置JavaScript 载入策略 小结

    JavaScript设计模式之策略模式详解

    这种解决方案就是所谓的策略模式。 策略模式的定义是:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。 /* * pre:策略模式 * 示例:公司计算奖金,分A、B、C 三种绩效,计算方式如下 * ...

    JavaScript设计模式之策略模式实例

    主要介绍了JavaScript设计模式之策略模式实例,本文分析了Jquery源码并给出了自己的实现,需要的朋友可以参考下

    学习JavaScript设计模式(策略模式)

    1、策略模式的定义 如果没有时间但是不在乎钱,可以选择坐飞机。 如果没有钱,可以选择坐大巴或者火车。 如果再穷一点,可以选择骑自行车。 在程序设计中,我们也常常遇到类似的情况,要实现某一个功能有多种方案...

    深入理解JavaScript系列.chm

    33.设计模式之策略模式 34.设计模式之命令模式 35.设计模式之迭代器模式 36.设计模式之中介者模式 37.设计模式之享元模式 38.设计模式之职责链模式 39.设计模式之适配器模式 40.设计模式之组合模式 41.设计模式之...

    深入理解JavaScript系列

    深入理解JavaScript系列(33):设计模式之策略模式 深入理解JavaScript系列(34):设计模式之命令模式 深入理解JavaScript系列(35):设计模式之迭代器模式 深入理解JavaScript系列(36):设计模式之中介者...

    深入理解JavaScript系列(.chm)

    深入理解JavaScript系列(33):设计模式之策略模式 深入理解JavaScript系列(34):设计模式之命令模式 深入理解JavaScript系列(35):设计模式之迭代器模式 深入理解JavaScript系列(36):设计模式之中介者...

    轻松掌握JavaScript策略模式

    一般用于在实现一个功能时,有很多个方案可选择的情况。  例子1:根据员工薪水salary、绩效等级S、A、B、C,来计算年终奖 //封装了所有算法的策略对象 var strategies = { 'S': function(salary){ return ...

    ASP.NET设计模式-杨明军译(源码)

    9.3.3 利用JavaScript Template实现数据绑定 9.3.4 Predictive Fetch 9.4 小结 第Ⅲ部分 案例研究:在线电子商务商店 第10章 需求和基础设施 10.1 Agatha服装店需求 10.1.1 Product Catalog和Basket截屏 ...

    JS表单验证插件之数据与逻辑分离操作实例分析【策略模式】

    主要介绍了JS表单验证插件之数据与逻辑分离操作,结合实例形式分析了JavaScript基于策略模式实现数据与逻辑分离的表单验证插件相关原理、操作技巧及注意事项,需要的朋友可以参考下

    js-pattern:js设计模式

    策略模式:根据不同命令命中不同算法,可以避免使用多重条件语句。 外观模式:将复杂的子系统功能隐藏在外观之后,提供简单的调用接口。 代理模式:通过包装一个对象以控制对它的访问,ES6中的Proxy就是通过代理扩展...

    JS设计模式之责任链模式实例详解

    本文实例讲述了JS设计模式之责任链模式。分享给大家供大家参考,具体如下: 责任链设计模式: 在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链。请求在这个链上传递,直到链上的某一个对象...

Global site tag (gtag.js) - Google Analytics