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.


Related articles: