An in depth understanding of the JavaScript series (33) : strategic patterns for design patterns
- 2020-05-10 17:41:00
- OfStack
introduce
The policy pattern defines a family of algorithms that are encapsulated so that they can be interchangeable, so that changes in the algorithm do not affect the customers who use the algorithm.
The body of the
Before understanding the strategy pattern, let's 1 example, 1 cases, data validity verification, if we want to do a lot of moment are judged according to the swith statement, but it has a few questions, first of all, if increased demand, we also need to modify the code again to increase the logic, but also when the unit test will be more and more complex, the code is as follows:
validator = {
validate: function (value, type) {
switch (type) {
case 'isNonEmpty ':
{
return true; // NonEmpty The verification results
}
case 'isNumber ':
{
return true; // Number The verification results
break;
}
case 'isAlphaNum ':
{
return true; // AlphaNum The verification results
}
default:
{
return true;
}
}
}
};
// test
alert(validator.validate("123", "isNonEmpty"));
Then 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 the unified policy processing class, OK. We first define the policy processing class, and the code is as follows:
var validator = {
// All possible validation rules handle where the class is stored and will be defined separately later
types: {},
// Validates the error message corresponding to the type
messages: [],
// Of course you need to use the authentication type
config: {},
// Exposed public validation methods
// The parameter passed in is key => value right
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]; // According to the key Query whether there is an existing validation rule
checker = this.types[type]; // Gets the validation class for the validation rule
if (!type) {
continue; // If the validation rule does not exist, it is not processed
}
if (!checker) { // If the validation rule class does not exist, throw an exception
throw {
name: "ValidationError",
message: "No handler to validate type " + type
};
}
result_ok = checker.validate(data[i]); // Use the single validation class found for validation
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;
}
};
All that's left is to define the various validation classes that are stored in types. Here are just a few examples:
// Verify that the given value is not null
validator.types.isNonEmpty = {
validate: function (value) {
return value !== "";
},
instructions: " The value passed in cannot be null "
};
// 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 valid number, such as: 1, 3.14 or 2010"
};
// Verify that the given value is just a letter or number
validator.types.isAlphaNum = {
validate: function (value) {
return !/[^a-z0-9]/i.test(value);
},
instructions: " Incoming values can only protect letters and Numbers, and cannot contain special characters "
};
When using it, we first need to define the data set to be validated, and then we need to define the rule type to be validated for each data. The code 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 get the validation results is simple:
validator.validate(data);
if (validator.hasErrors()) {
console.log(validator.messages.join("\n"));
}
conclusion
The policy pattern defines a series of 1 algorithms. Conceptually, all of these algorithms do the same thing, but with different implementations. They can call all methods in the same way, reducing the coupling between the various algorithm classes and the classes using the algorithm.
On another level, it is also convenient to define the algorithm class separately, because it can be tested separately through one's own algorithm.
In practice, you can encapsulate not only algorithms, but also almost any type of rule. If you need to apply different business rules at different times during the analysis process, you can consider the policy pattern to handle various changes.