What is strategy? For example, we want to go to a place to travel, can be based on the actual situation to choose the route of travel.
1, the definition of the policy model
If you don't have time but don't care about money, you can choose to take a plane.
If there is no money, you can choose to take the bus or train.
If you are poorer, you can choose to ride a bike.
In the program design, we also often encounter a similar situation, to achieve a certain function has a variety of options to choose from. For example, a compressed file program, you can choose either the zip algorithm, or the GZIP algorithm can be selected.
definition: The policy pattern defines a series of algorithms that are packaged separately so that they can be replaced by each other, and this pattern allows the algorithm to change independently from the customer who uses the rice.
The strategy model has a wide range of applications. This section gives an example of the year-end award.
2. Examples of year-end awards
Many companies ' year-end bonuses are based on the salary base and year-end performance of the employee. For example, the person who has a performance of S is 4 times times the salary, the person with a performance of the year award is 3 times times the salary, and the person who has the performance of B is twice times the salary of the year-end award. Suppose the Finance department asks us to provide a piece of code to help them calculate their employees ' year-end bonuses.
1). The initial Code implementation
We can write a function called Calculatebonus to calculate the bonus amount for each person. Obviously, the Calculatebonus function needs to receive two parameters to work correctly: the employee's salary amount and his performance appraisal level. The code is as follows:
var calculatebonus = function (Performancelevel, salary) {
if (performancelevel = = = ' S ') {return
salary * 4;
}
if (performancelevel = = ' A ') {return
salary * 3;
}
if (Performancelevel = = ' B ') {return
salary * 2;
}
};
Calculatebonus (' B ', 20000); Output: 40000
calculatebonus (' S ', 6000);//output: 24000
As you can see, this code is simple, but there are obvious drawbacks.
The Calculatebonus function is large and contains a number of if-else statements that need to overwrite all logical branches.
The Calculatebonus function lacks elasticity, if a new performance grade C is added, or if you want to change the bonus factor of performance S to 5, then we have to delve into the internal implementation of the Calculatebonus function, which violates the open-closed principle.
The algorithm's reusability is poor, if you need to reuse the algorithm in other parts of the program to calculate the bonus? Our choice is only to copy and paste. So, we need to refactor this code.
2). Using composite functions to refactor code
The easiest way to think about it is to refactor it using a combination of functions, and we encapsulate the various algorithms into small functions that have a good name and a clear idea of which algorithm they correspond to and can be reused elsewhere in the program. The code is as follows:
var performances = function (Salary) {return
salary * 4;
};
var performancea = function (Salary) {return
salary * 3;
};
var performanceb = function (Salary) {return
salary * 2;
};
var calculatebonus = function (Performancelevel, salary) {
if (performancelevel = = = ' S ') {return
performances ( salary);
}
if (Performancelevel = = ' A ') {return
performancea (salary);
}
if (Performancelevel = = ' B ') {return
performanceb (salary);
}
};
Calculatebonus (' A ', 10000); Output: 30000
At present, our procedures have been improved somewhat, but this improvement is very limited, we still do not solve the most important problem: The Calculatebonus function is likely to become larger, and when the system changes in the lack of flexibility.
3). Refactoring Code using policy mode
After thinking about it, we thought of a better way to refactor the code using the policy pattern. A strategy pattern is defined as a series of algorithms that encapsulate them. Separating the invariant parts from the changed parts is the subject of each design pattern, and the policy pattern is designed to separate the use of the algorithm from the implementation of the algorithm.
In this example, the algorithm is used in the same way, is based on an algorithm to obtain the calculated bonus amount. The implementation of the algorithm varies and varies, and each performance corresponds to a different calculation rule.
A program based on policy mode consists of at least two parts. The first part is a set of policy classes that encapsulate specific algorithms and are responsible for specific computational processes. The second part is that the Environment class Context,context accept the customer's request and then delegate the request to a policy class. To do this, you need to maintain a reference to a policy object in the context.
Now use the policy mode to refactor the code above. The first version is a simulation of an implementation in a traditional object-oriented language. We first encapsulate the calculation rules for each performance in the corresponding policy class:
var performances = function () {};
PerformanceS.prototype.calculate = function (Salary) {return
salary * 4;
};
var performancea = function () {};
PerformanceA.prototype.calculate = function (Salary) {return
salary * 3;
};
var performanceb = function () {};
PerformanceB.prototype.calculate = function (Salary) {return
salary * 2;
};
Next define the Bonus class bonus:
var Bonus = function () {
this.salary = null;//original wage
this.strategy = null;//performance level corresponding policy Object
};
Bonus.prototype.setSalary = function (Salary) {
this.salary = salary;//Set up employee's original salary
};
Bonus.prototype.setStrategy = function (strategy) {
this.strategy = strategy;//Set policy object corresponding to employee performance level
};
Bonus.prototype.getBonus = function () {//Get bonus amount return
this.strategy.calculate (this.salary); Delegate the operation of the bonus calculation to the corresponding policy object
};
Before we complete the final code, we'll revisit the idea of the strategy model:
Define a series of algorithms that encapsulate them one by one and allow them to replace each other.
If you say this in more detail, you define a series of algorithms that encapsulate them into policy classes, and the algorithms are encapsulated in methods within the policy class. When a client initiates a request to the context, the context always delegates the request to one of these policy objects for calculation.
"And make them interchangeable," is largely relative to the static type language. Because there is a type checking mechanism in the static type language, each policy class needs to implement the same interface. When their true types are hidden behind an interface, they can be replaced by each other. There is no such problem with JavaScript in a "type fuzzy" language, where any object can be replaced. As a result, "interchangeable use" in JavaScript is shown to have the same goals and intentions.
Now let's finish the rest of the code in this example. First create a bonus object and set some raw data to the bonus object, such as the employee's original salary amount. Next, the policy object for a calculated bonus is also passed into the bonus object to be saved internally. When the Bonus.getbonus () is invoked to calculate the bonus, the bonus object itself is not capable of computing, but the request is delegated to the previously saved policy object:
var bonus = new bonus ();
Bonus.setsalary (10000);
Bonus.setstrategy (new performances ()); Set Policy Object
Console.log (Bonus.getbonus ());//output: 40000
bonus.setstrategy (New Performancea ());//Set Policy Object
Console.log (Bonus.getbonus ()); Output: 30000
We've just reconstructed this year's year-end bonus code with a policy model, and we can see that the code becomes clearer after the policy pattern is refactored, and that the responsibilities of each class are sharper. But this code is based on the traditional object-oriented language, and in the next section we'll look at the policy patterns implemented with JavaScript.
In section 5.1, we let the strategy object be created from each policy class, which simulates the implementation of some traditional object-oriented languages. In fact, in JavaScript languages, functions are also objects, so the simpler and more straightforward approach is to define strategy directly as a function:
var strategies = {
"S": function (Salary) {return
salary * 4;
},
' A ': function (Salary) {return
S Alary * 3;
},
"B": function (Salary) {return
salary * 2;
}
;
Similarly, there is no need for the context to be represented by the bonus class, and we still use the Calculatebonus function as the context to accept the user's request. After transformation, the structure of the code becomes more concise:
var strategies = {
"S": function (Salary) {return
salary * 4;
},
' A ': function (Salary) {return
sala RY * 3;
},
"B": function (Salary) {return
salary * 2;
}
;
var Calculatebonus = function (level, salary) {return
strategies[level] (salary);
Console.log (Calculatebonus (' S ', 20000)); Output: 80000
console.log (Calculatebonus (' A ', 10000));//output: 30000
3, the example again explained
A small example will give us a clear glance.
Recall the Animate method in jquery.
$ (div). Animate ({"left:200px"}, 1000, ' linear ');
Uniform Motion
$ (div). Animate ({"left:200px"}, 1000, ' cubic ');
Three-second side of the slow motion
The 2-sentence code is to have the div move 200 pixels to the right within 1000ms. Linear (constant) and cubic (three-second-order easing) are the encapsulation of a policy pattern.
One more example. Many pages will have an instant-validated form. Each member of the form has a different validation rule.
For example, the name box, you need to verify the non-empty, sensitive words, characters too long in these situations. Of course, you can write 3 if else to solve, but the extension and maintenance of this writing code is conceivable. If there are more elements in the form, there is a bit more to verify, and it is not impossible to add hundreds of if else.
So the better approach is to encapsulate each validation rule separately with the policy pattern. The name of the policy is only required when the validation is required. Just like this:
Nameinput.addvalidata ({
notnull:true,
dirtywords:true,
maxlength:30
})
and Notnull, Methods such as MaxLength only need to return true or false uniformly to indicate whether validation has been passed.
validatalist = {
Notnull:function (value) {return
value!== ';
},
maxlength:function (value, MA Xlen) {return
value.length () > MaxLen;
}
}
As you can see, the various validation rules are easily modified and replaced by each other. If one day the Product manager recommends that the length of the characters be changed to 60 characters. It only takes 0.5 seconds to finish the work.
About the content for everyone to introduce to this.
Talk about the digression, immediately 2015 to pass, everyone's year-end award is not very rich AH!!!
I hope that you can have a harvest in this year, through this article can also be harvested, know what is a strategic model, understanding small compiled meticulously for everyone prepared two examples.