define

Define a set of algorithms, encapsulate them one by one, and make them interchangeable. A policy-based program consists of at least two parts:

  1. Policy class: encapsulates the specific algorithm and is responsible for the specific calculation process
  2. Context class Context:ContextAccept the client request and then delegate the request to the policy class

Real world analogy

If you need to get to the airport. You can choose to take a bus, book a taxi or ride a bike. These are your travel strategies. You can choose one of these strategies based on factors such as budget or time.

Mode realization – Calculate bonuses

Here we take the calculation of annual bonus as an example to achieve:

Let’s say the person with S gets 4 times their salary at the end of the year; Person A gets A year-end bonus of three times his salary; B gets twice his salary as a year-end bonus.

According to the basic components of the strategy pattern, we break it down:

// Step 1: Encapsulate the policy class
const strategies = {
  S: salary= > {
    return salary * 4;
  },
  A: salary= > {
    return salary * 3;
  },
  B: salary= > {
    return salary * 2; }};// Step 2: Here we use the calculateBonus function as the Context to receive the user request
const calculateBonus = (level, salary) = > {
  return strategies[level](salary);
};

console.log(calculateBonus("S".20000)); // Output: 80000
console.log(calculateBonus("A".10000)); // Output: 30000
Copy the code

A more generalized “algorithm”

The strategy pattern refers to defining a set of algorithms. In practice, however, we often diffuse the meaning of algorithms so that policy patterns can also be used to encapsulate a set of business rules. As long as the business rules point to the same goal and can be used interchangeably.

Pattern implementation – form validation

In Web applications, forms are almost always validated.

Suppose we are writing a registration page and need to verify the following logic before clicking the register button:

  • The user name cannot be empty
  • The password contains at least six characters
  • The mobile phone number must conform to the format
// Step 1: Encapsulate the policy class
const strategies = {
  isNonEmpty: (value, errorMsg) = > {
    if (value === "") {
      returnerrorMsg; }},minLength: (value, errorMsg) = > {
    if (value.length < 6) {
      returnerrorMsg; }},isMobile: (value, errorMsg) = > {
    if (!/ (a ^ 1 [3 | | 5 8] [0-9] {9} $) /.test(value)) {
      returnerrorMsg; }}};// Step 2: Encapsulate the Validator class as a Context to receive user requests and delegate to the Strategy object
class Validator {
  constructor() {
    this.cache = [];
  }
  add(dom, strategy, errorMsg) {
    this.cache.push((a)= > {
      const args = [dom.value, errorMsg];
      return strategies[strategy].apply(dom, args);
    });
  }
  start() {
    this.cache.forEach(fn= > {
      const msg = fn();
      if (msg) {
        returnmsg; }}); }}/ / use
const registerForm = document.getElementById("registerForm");
function validataFunc() {
  const validator = new Validator();
  validator.add(registerForm.userName, "isNonEmpty"."User name cannot be empty");
  validator.add(registerForm.password, "minLength"."Password length must not be less than 6 characters.");
  validator.add(registerForm.phone, "isMobile"."Mobile phone number format is incorrect");
  const error = validator.start();
  return error;
}
registerForm.onsubmit = (a)= > {
  const errorMsg = validataFunc();
  if (errorMsg) {
    alert(errorMsg);
    return false; }};Copy the code

As you can see, we have verified a form just by configuring it.

summary

In the policy pattern of JavaScript language, policy classes are often replaced by functions, and the policy pattern becomes an “invisible” pattern. Nonetheless, the idea of a fundamental understanding of strategic patterns not only gives us a better understanding of patterns, but also the benefits of using functions.

reference

  • Deep Design Patterns
  • JavaScript Design Patterns and Development Practices