“This is the ninth day of my participation in the August More Text Challenge. For details, see: August More Text Challenge.”
preface
At the top end of the interview, often encounter some questions about design patterns, each time the answer is not ideal. Coincides with the more challenging activities in August, I am prepared to spend a month to get a good understanding of design patterns, so as to increase my confidence for the interview.
The six principles of design patterns have been described in detail in previous articles:
- “Interview confidence” — The single Responsibility principle of design mode | more challenging in August
- “The confidence of interview” — the open and Closed principle of design mode | more challenging in August
- “Interview confidence” — the least knowledge principles of design patterns | more challenging in August
- “The Strength of interview” — The Richter’s Principle of substitution in Design mode | more challenging in August
- “The Strength of the interview” — The Design pattern relies on the Inversion principle | more challenging in August
- “The strength of interview” – Interface Isolation principles in design patterns | more challenging in August
Next, let’s study and practice the strategic pattern of design patterns. In the process of practice, strictly follow the six principles. If you are not familiar with the principles, you can visit the corresponding link above.
define
Strategy pattern: Define a set of algorithms, encapsulate them one by one, and make them interchangeable.
Implement a simple policy pattern
For example, many companies have performance appraisal every month and pay performance bonus after the appraisal. For example, the performance bonus for S is 0.2 times the salary, the performance bonus for A is 0.1 times the salary, the performance bonus for B is 0 times the salary, and the performance bonus for C is -0.1 times the salary. Suppose the human resources department asks us for a piece of code that will allow them to calculate the monthly performance bonus of an employee.
Cosnt calculateBonus = (level, salary) =>{if (level === 'S') {return salary * 0.2; } if (level === 'A') {return salary * 0.1; } if (level === 'B') { return salary * 0; } if (level === 'C') {return salary * -0.1; }}; calculatebonus('S', 20000); // Output: 4000 calculateBonus ('A', 6000); // Output: 600Copy the code
The above code is simple enough to fulfill the needs of the hr department, but it has obvious drawbacks.
calculatebonus
It’s a big function, it contains a lot of thingsif-else
Statements that need to override all logic
Branch.
calculatebonus
Function scalability is poor if you add a new performance grade D, or want to put performance C bonus
To change the coefficient to 0, we would have to dig into the internal implementation of the CalculateBonus function, which violates the open-close principle.
- The algorithms are not reusable. What if you need to reuse the algorithms for performance bonuses elsewhere? Do you want to copy and paste the past.
The above disadvantages can be well solved with the strategy mode. Therefore, we need to refactor this code.
The strategy pattern refers to defining a set of algorithms, encapsulating them one by one, and separating their use from their implementation. Separating the parts that do not change from the parts that change is a theme of every design pattern, and policy patterns are no exception.
A program based on the policy pattern consists of at least two parts. The first is a set of policy classes that encapsulate specific algorithms and are responsible for specific computing processes. The second part is the environment class, which accepts the request from the customer and then delegates it to one of the policy classes. To do this, a reference to a policy object is maintained in the environment class.
So the first step is to encapsulate the performance bonus algorithm and make a strategy class.
Class LevelS {calculate(salary) {return salary * 0.2; }} class levelA {calculate(salary) {return salary * 0.1; } } class levelB { calculate(salary) { return salary * 0; }} class levelC {calculate(salary) {return salary * -0.1; }}Copy the code
Then create an environment class (Bonus for performance pay)
class Bonus { constructor(... arguments) { this.salary = null; This.strategy = null; } setSalary(salary) {this.salary = salary; } setStrategy(strategy) {this.strategy = strategy; } getBonus(){return this.strategy.calculate(this.salary); // Calculate performance pay}}Copy the code
How to use it? To review the definition of the policy pattern: “Define a set of algorithms, encapsulate them one by one, and make them interchangeable.” Explain a little bit more. Define a set of algorithms, each encapsulated as a policy class, and the algorithm is encapsulated in the methods inside the policy class. When a customer initiates a request to the environment class, the environment class always delegates the request to a policy class and invokes the algorithm in the policy class.
In the example above, the Bonus class is the environment class, and the request made by the customer to the environment class instantiates an environment class. Call bonus. SetStrategy to delegate to a policy class.
const bonus = new Bonus(); bonus.setSalary( 20000 ); // Set salary bonus. SetStrategy (new LevelS()); // Set the policy object console.log(bonus. GetBonus ()); // Output: 4000 bonus. SetSalary (6000); Bonus. SetStrategy (new LevelA()); // Set the policy object console.log(bonus. GetBonus ()); // Output: 600Copy the code