introduce
The strategy model defines the algorithm family and encapsulates them separately so that they can replace each other. This model allows changes in the algorithm to not affect customers using the algorithm.
text
Before understanding the policy model, let’s first take an example. Generally speaking, if we want to verify the data legitimacy, we often judge according to the sweep statement, but this brings several problems. First of all, if we increase the demand, we have to modify this code again to increase the logic, and it will become more and more complicated when conducting unit tests. The code is as follows:
The code copy is as follows:
validator = {
validate: function (value, type) {
switch (type) {
case 'isNonEmpty ':
{
return true; // NonEmpty verification result
}
case 'isNumber':
{
return true; // Number Verification result
break;
}
case 'isAlphaNum ':
{
return true; // AlphaNum verification result
}
default:
{
return true;
}
}
}
};
// test
alert(validator.validate("123", "isNonEmpty"));
So how to avoid the problems in the above code? According to the policy pattern, we can encapsulate the same working code into different classes separately, and then handle it through a unified policy processing class. OK, we first define the policy processing class, the code is as follows:
The code copy is as follows:
var validator = {
// All places where all validation rules processing classes can be stored will be defined separately later
types: {},
// Error message corresponding to the verification type
messages: [],
// Of course, the verification type that needs to be used
config: {},
// Exposed public verification method
// The passed parameter is key => value pair
validate: function (data) {
var i, msg, type, checker, result_ok;
// Clear all error messages
this.messages = [];
for (i in data) {
if (data.hasOwnProperty(i)) {
type = this.config[i]; // Check whether there is a validation rule based on key
checker = this.types[type]; // Get the verification class for the verification rule
if (!type) {
continue; // If the verification rule does not exist, it will not be processed
}
if (!checker) { // If the verification rule class does not exist, an exception is thrown
throw {
name: "ValidationError",
message: "No handler to validate type " + type
};
}
result_ok = checker.validate(data[i]); // Verify using a single verification class found
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;
}
};
Then the rest is to define the various verification classes stored in types. Let's give you a few examples here:
The code copy is as follows:
// Verify that the given value is not empty
validator.types.isNonEmpty = {
validate: function (value) {
return value !== "";
},
instructions: "The value passed cannot be empty"
};
// Verify that the given value is a number
validator.types.isNumber = {
validate: function (value) {
return !isNaN(value);
},
Instructions: "The value passed in can only be a legal number, for example: 1, 3.14 or 2010"
};
// Verify that the given value is just a letter or a number
validator.types.isAlphaNum = {
validate: function (value) {
return !/[^a-z0-9]/i.test(value);
},
Instructions: "The passed value can only protect letters and numbers and cannot contain special characters"
};
When using it, we first need to define the data set that needs to be verified, and then we need to define the rule type that needs to be verified for each data. The code is as follows:
The code copy is as follows:
var data = {
first_name: "Tom",
last_name: "Xu",
age: "unknown",
username: "TomXu"
};
validator.config = {
first_name: 'isNonEmpty',
age: 'isNumber',
username: 'isAlphaNum'
};
Finally, the code to obtain the verification result is simple:
The code copy is as follows:
validator.validate(data);
if (validator.hasErrors()) {
console.log(validator.messages.join("/n"));
}
Summarize
The strategy pattern defines a series of algorithms. Conceptually, all of these algorithms do the same thing, but the implementation is different. They can call all methods in the same way, reducing the coupling between various algorithm classes and the algorithm classes used.
From another level, defining the algorithm class separately also facilitates unit testing, because it can be tested separately through your own algorithm.
In practice, not only algorithms can be encapsulated, but also almost any type of rules. It is necessary to apply different business rules at different times during the analysis process, so you can consider that the policy model is needed to handle various changes.