The definition of a strategy pattern is to define a series of algorithms, encapsulate them one by one, and make them interchangeable.

  • The policy pattern avoids multiple judgment criteria in code.
  • The strategy pattern well embodies the open-closed principle and encapsulates each algorithm (solution) in a strategy class. Easy to switch, understand, and expand.
  • The various algorithms in the policy can be reused in various parts of the system, avoiding copy and paste.
  • Policy mode adds more or less policy classes to the program. But it’s clearer than stacking it up in business logic.
  • In violation of the minimum knowledge principle, you must understand various policy classes to better apply them in business.

This article is just a record of my feelings while reading the book JavaScript Design Patterns and Development Practices. I thank the author for writing such a good book. If there is any offense, if there is any mistake, please contactI amTo deal with.

Simple business scenario

To calculate employees’ annual bonus, different bonuses should be calculated according to different employees’ performance. For example, someone with a performance of S gets four times their salary at the end of the year. The A person gets 3 times his annual bonus, the B person gets 2 times his salary.

With code:

var calculateBonus = function(performanceLevel, salary) {
    if (performanceLevel === 'S') {
        return salary * 4
    }
    if (performanceLevel === 'A') {
        return salary * 3
    } 
    if (performanceLevel === 'B') {
        return salary * 2
    }
}

calculateBonus('S'.2000) / / 8000
calculateBonus('A'.2000) / / 6000
Copy the code

In fact, the above code can handle the current scenario. However, when the bonus evaluation needs to add A performance C, or change the way performance A is calculated. At this point, you need to change the internal structure of the calculateBonus method above, and the method will become bloated internally.

An important part of design patterns is the separation of immutable and variable. Here’s what’s changed. What doesn’t change is getting a result based on a performance. So the code was rewritten to encapsulate the various algorithms in policy classes (traditional object-oriented mimicry) :

var performanceS = function() {}
performanceS.prototype.calc = function(salary) {
    return salary * 4
}

var performanceA = function() {}
performanceA.prototype.calc = function(salary) {
    return salary * 3
}

var performanceB = function() {}
performanceB.prototype.calc = function(salary) {
    return salary * 2
}

// Class Bonus
var Bonus = function() {
    this.salary = null // Original salary
    this.strategy = null // The policy object corresponding to the performance level
}

Bonus.prototype.setSalary = function(salary) {
    this.salary = salary // Set the salary
}

Bonus.prototype.setStrategy = function(strategy) {
    this.strategy = strategy // Set the policy object corresponding to employee performance
}

Bonus.prototype.getBonus = function() { // Get the amount of bonus
    return this.strategy.calc(this.salary) // Delegate the bonus calculation to a corresponding policy object
}

var bonus = new Bonus()
bonus.setSalary(10000)
bonus.setStrategy(new performanceA())

console.log(bonus.getBonus()) / / 30000
Copy the code

JavaScript version of the policy pattern

In JavaScript, you can write each policy class as a function and wrap it in an object:

// Calculate the bonus example
var strategies = {
    S: function(salary) {
        return salary * 4
    },
    A: function(salary) {
        return salary * 3
    },
    B: function(salary) {
        return salary * 2}}var calculateBonus = function(level, salary) {
    return strategies[level](salary)
}

console.log(calculateBonus('S'.10000)) / / 40000
console.log(calculateBonus('S'.20000)) / / 80000
Copy the code

A more generalized “algorithm”

A policy pattern refers to a set of algorithms (policies) that encapsulate them. Some algorithms are encapsulated in the column that calculates the bonus. In fact, policy patterns can be used to encapsulate some “business rules” in century business.

Form validation

There are often many scenarios in a Web project that require submission of forms. The front end needs to do a wave of form validation to reduce unnecessary network requests before submitting data to the back end. There are often multiple validation rules in form validation, and pages may have multiple forms to validate. At this point, you can implement a form validation using policy mode:

<form action="" mothod="post" id="registerForm">Enter a user name:<input type="text" name="userName">Enter your password:<input type="text" name="password">Enter your mobile phone number:<input type="text" name="phoneNumber">
  <button>submit</button>
</form>
<script>
    var strategies = {
      isNonEmpty: function(value, errorMsg){
        if(value === ' ') {return errorMsg
        }
      },
      minLength: function(value, length, errorMsg){
        if(value.length < length){
          return errorMsg
        }
      },
      isMobile: function(value, errorMsg){
        if(!/ (a ^ 1 [3 | | 5 8] [0-9] {9} $) /.test(value)){
          return errorMsg
        }
      }
    }

    // Define the Validator class
    var Validator = function(){
      this.cache = []
    }

    Validator.prototype.add = function(dom, rule, errorMsg){
      var ary = rule.split(':')
      this.cache.push(function(){
        var strategy = ary.shift()
        ary.unshift(dom.value)
        ary.push(errorMsg)
        return strategies[ strategy ].apply(dom, ary)
      })
    }

    Validator.prototype.start = function(){
      for (var i = 0,validatorFunc; validatorFunc =this.cache[i++];) {var msg = validatorFunc()
        if(msg){
          return msg
        }
      }
    }

    var validataFunc = function() {
      var validator = new Validator()
    // Add the verification rule
      validator.add(registerForm.userName,'isNonEmpty'.'User name cannot be empty')
      validator.add(registerForm.password,'minLength:6'.'Password length must not be less than 6 characters')
      validator.add(registerForm.phoneNumber,'isMobile'.'Phone format is not correct')

      var errorMsg = validator.start()
      return errorMsg
    }

    var registerForm = document.getElementById('registerForm')
    registerForm.onsubmit = function(){
      var errorMsg = validataFunc()
      if (errorMsg) {
        console.log(errorMsg)
        return false}}</script>
Copy the code

conclusion

  • In daily development, some tool functions can be encapsulated together to form their own tool library. Reduce unnecessary code copy and paste.
  • The idea of knock-on code is more important, where the policy pattern embodies the open-close principle of reducing the coupling of code. These are all ideas THAT I learned and accumulated on the way to code.
  • You can’t just type out code that you know. Pay attention to detail and always think about what code could be improved more.
  • Of course, not everything has to be divided, and a simple requirement to design patterns for the sake of designing patterns is not desirable.

love & peace

Originally posted by Roy’s Blog

reference

“JavaScript Design Patterns and Development Practices” — Zeng