preface
In software engineering, design pattern is a solution to various problems commonly existing (recurring) in software design.
Design patterns are not used to write code directly, but rather to describe how to solve a problem in a variety of situations.
Design patterns enhance the ability of software designs to face and adapt to change by turning instability into relative stability and concrete into relative abstraction, avoiding troublesome tight coupling
— Wikipedia
Design pattern is an idea of software development, which is beneficial to reduce the coupling of code and enhance the robustness of code. They are often used in large projects.
Today, I’ll introduce a design pattern that can replace the choice operation — the strategy pattern.
introduce
As a software design pattern, policy pattern refers to a certain behavior of the object, but in different scenarios, the behavior has different implementation algorithms. For example, everyone has to “pay personal income tax”, but “pay personal income tax in the United States” and “pay personal income tax in China” have different ways of calculating tax.
Strategy mode:
- Defines a family of algorithms (business rules);
- Encapsulate each algorithm;
- Algorithms of this family are interchangeable.
— Wikipedia
It can be seen that in order to deal with different algorithms caused by different scenarios, each algorithm is encapsulated into classes based on factory mode and then used, which is the strategy mode.
case
In general, if we want to verify the validity of data, we usually use swith statements (also if, elseif, else), but this causes several problems:
- If we add requirements, we’ll have to modify this code again to add logic.
- It also gets more complex as you do unit tests.
The code is as follows:
validator = {
validate: function(value, type) {
switch (type) {
case "isNonEmpty ": {
return true;
}
case "isNumber ": {
return true;
break;
}
case "isAlphaNum ": {
return true;
}
default: {
return true; }}}};/ / test
alert(validator.validate("123"."isNonEmpty"));
Copy the code
How to avoid the problem in the above code? According to the policy pattern, we can separate the same working code into different classes, and then use the uniform policy processing class to handle, OK, let’s define the policy processing class, the code is as follows:
var validator = {
// Where all available validation rule processing classes are stored will be defined separately later
types: {},
// Verify the error message corresponding to the type
messages: [],
// Of course you need to use the validation type
config: {},
// Exposed public validation methods
// The argument passed in 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 are authentication rules based on the key
checker = this.types[type]; // Get the validation class of the validation rule
if(! type) {continue; // If the validation rule does not exist, no action is taken
}
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 a 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; }};Copy the code
The rest of the job then 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) {
returnvalue ! = ="";
},
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 letters or numbers
validator.types.isAlphaNum = {
validate: function(value) {
return !/[^a-z0-9]/i.test(value);
},
instructions: "The value passed in can only protect letters and numbers and cannot contain special characters."
};
Copy the code
To use it, we need to define the set of data to validate, and then we need to define the rule types for each data to validate, as follows:
var data = {
first_name: "Tom".last_name: "Xu".age: "unknown".username: "TomXu"
};
validator.config = {
first_name: "isNonEmpty".age: "isNumber".username: "isAlphaNum"
};
Copy the code
Finally, the code to get the validation results is simple:
validator.validate(data);
if (validator.hasErrors()) {
console.log(validator.messages.join("\n"));
}
Copy the code
conclusion
The policy pattern defines a set of algorithms, all of which conceptually do the same thing, but implement different things. They can call all methods in the same way, reducing the coupling between various algorithm classes and using algorithm classes.
On another level, defining algorithm classes separately also facilitates unit testing because you can test them individually with your own algorithms.
In practice, it can be used to encapsulate not only algorithms, but also almost any type of rules. If different business rules need to be applied at different times in the analysis process, it can be considered as a strategic pattern to deal with various changes.
-EFO-
The author specially created a repository on Github, which is used to record the skills, difficulties and easy mistakes in learning full stack development. Please click the link below to browse. If you feel good, please give a little star! 👍
2019/04/24
AJie