JavaScript学习笔记(四十五) 策略

策略模式(Strategy)

策略模式能够让你在运行时选择算法。你的代码使用者可以处理相同的接口但可以从一些可用的算法中挑选算法去处理他们具体的任务,依赖于他们打算做什么的环境。

一个使用策略模式的示例将是处理表单验证。你可以通过validate()方法创建一个验证器(validator)对象,这个方法将会被调用,不管表单的具体类型并始终返回相同的结果——一个没有验证的数据的list和任何错误信息。

但依赖于具体的表单和数据去验证,你的代码使用者可能选择不同类型的检查。你的验证器选择最佳的策略(strategy)去处理任务并委托具体数据的检查给适当的算法。

数据验证示例(Data Validation Example)

假设你有下面这段数据,可能从页面的表单中得到的,并且你想验证是否是合法的:
var data = {
    first_name: "Super",
    last_name: "Man",
    age: "unknown",
    username: "o_O"
};
为了让验证器知道在这个具体的例子中哪个是最佳策略,你需要首先要配置验证器并设置你认为是合法和可接受的规则。

假设你将不要求last name且fist name可以随意输入,但你要求age是一个数字且username只能由字母和数字组成并不能有特殊字符。配置可能看起来像这样:
validator.config = {
    first_name: 'isNonEmpty',
    age: 'isNumber',
    username: 'isAlphaNum'
};
现在validator对象被配置为了处理你的数据,你调用它的validate()方法并打印验证错误到控制台:
validator.validate(data);
if (validator.hasErrors()) {
    console.log(validator.messages.join("\n"));
}
这可能打印下面的错误信息:
Invalid value for *age*, the value can only be a valid number, e.g. 1, 3.14 or 2010
Invalid value for *username*, the value can only contain characters and numbers, no special
symbols
现在让我们看一下如何实现validator方法。检查用的算法是预定义接口的对象——它们提供一个validator()方法和一行被用在错误信息(error message)里的帮助信息(help infomation):
// checks for non-empty values
validator.types.isNonEmpty = {
    validate: function(value) {
        return value !== "";
    },
    instructions: "the value cannot be empty"
};
// checks if a value is a number
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"
};
// checks if the value contains only letters and numbers
validator.types.isAlphaNum = {
    validate: function(value) {
        return ! /[â-z0-9]/i.test(value);
    },
    instructions: "the value can only contain characters and numbers, no special symbols"
};

最终核心的validator对象:
 var validator = {
    // all available checks
    types: {},
    // error messages in the current
    // validation session
    messages: [],
    // current validation config
    // name: validation type
    config: {},
    // the interface method
    // `dataìs key => value pairs
    validate: function(data) {
        var i, msg, type, checker, result_ok;
        // reset all messages
        this.messages = [];
        for (i in data) {
            if (data.hasOwnProperty(i)) {
                type = this.config[i];
                checker = this.types[type];
                if (!type) {
                    continue; // no need to validate
                }
                if (!checker) { // uh-oh
                    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;
    }
 };
正如你看到的,validator对象是通用的并可以对所有验证用例这样保持这样。改进的办法可能是增加更多类型的检查。如果你在一些页面上使用它,不久你将拥有一批非常好的检查(check)。然后你所需要做的为每个新用例配置验证器并运行validate()方法。




猜你喜欢

转载自blog.csdn.net/qq838419230/article/details/10474627