I try to explain all aspects of the design pattern in the least amount of text and space.
Full Text Connection
Understanding Strategic Patterns
Split the algorithm from the part calling it
Let me give you an example: You want to travel to Sanya in many ways: by plane, by train, by car.These methods can all reach the destination, but the process is different.
- Airplane: Suitable for emergency money
- Train: suitable for non-emergency and clear purpose (company group building, middle-aged and elderly tourism)
- Self-driving tour: This kind of more casual, go out with friends and family, enjoy the scenery passing by.
Each choice is a strategy.
Strategies in the program are meant to integrate code that handles different tasks but serves the same purpose.They are delegated with one more level of functionality to work with specific algorithms.This eliminates the large number of conditional branching statements in the original program
Code above: Policy mode (calculating arrival times for different modes of travel)
// Define policies var strategies = { 'plane': function(distance) { return distance * 1; // Assume that the airplane is the fastest }, 'train': function(distance) { return distance * 4; // The speed of an airplane is four times that of a train }, 'roadTrip': function(distance) { return distance * 10; // The speed of an airplane is 10 times that of a driving tour }, } // Context var calculateBonus = function(mode, distance) { if (typeof strategies[mode] === 'function') { return strategies[mode](distance); } return -1; } // Invoke Policy console.log(calculateBonus('plane', 1000)); console.log(calculateBonus('train', 1000)); console.log(calculateBonus('roadTrip', 1000));
Strategic Patterns are easy to understand. Let's first look at a piece of code that will be transformed by Strategic Patterns.
Before using policy mode
var calculateBonus = function(mode, distance) { if (mode === 'plane') { return distance * 1; } else if (mode === 'train') { return distance * 4; } else if (mode === 'roadTrip') { return distance * 10; } return -1; }
The biggest problem with this piece of code is that it is not reproducible enough to be maintained.Every time a new change occurs, the code must be scraped open to find a specific function to modify.Low efficiency, prone to consistency errors.
Use strategy mode to achieve slow understanding of animation functions
To clarify the scenario in which the strategy pattern is used, let's implement an animation function together.
The js animation principle changes the css properties of the dom, such as left, top, background-position.So at least provide some information.
- dom initial position
- Target location
- start time
- End time
Then, with the timer setInterval, the css property of the dom is changed once every 19 milliseconds in the timer, and the four parameters above are passed to the algorithm each time the dom is modified.The algorithm calculates where it should be.Finally, the css property of the dom is updated.This completes the animation.
Algorithmic section, originally from Flash, but now also from css3
// Define the animation slowdown algorithm first var tween = { linear: function(t, b, c, d) { return c * t / d + b; }, easeIn: function(t, b, c, d) { return c * (t /= d) * t + b; }, strongEaseIn: function(t, b, c, d) { return c * (t /= d) * t * t * t * t + b; }, strongEaseOut: function(t, b, c, d) { return c * ((t = t / d - 1) * t * t * t * t + 1) + b; }, sineaseIn: function(t, b, c, d) { return c * (t /= d) * t * t + b; }, sineaseOut: function(t, b, c, d) { return c * ((t = t / d - 1) * t * t + 1) + b; } }
Then add the next node to the body
<div style="position: absolute; background:yellow;">im div</div>
Next, define the animation class
let Animate = function(dom) { this.dom = dom; this.startTime = 0; this.startPos = 0; this.endPos = 0; this.propertyName = null; this.esing = null; this.duratin = null; } Animate.prototype.start = function(propertyName, endPos, duratin, esing) { this.startTime = Date.now(); this.startPos = this.dom.getBoundingClientRect()[propertyName]; this.propertyName = propertyName; this.endPos = endPos; this.duratin = duratin; this.esing = tween[esing]; let self = this; let timeId = setInterval(function() { if (self.step() === false) { clearInterval(timeId) } }, 19) } Animate.prototype.step = function() { var t = Date.now(); if (t >= this.startTime + this.duratin) { this.update(this.endPos) return false } var pos = this.esing( t - this.startTime, // time this.startPos, // Beginning value this.endPos - this.startPos, // Motion Distance this.duratin // Time taken for tests ) this.update(pos); } Animate.prototype.update = function(pos) { this.dom.style[this.propertyName] = pos + 'px'; }
To test it!
var div = document.getElementsByTagName('div')[0]; var animate = new Animate(div); animate.start('left', 500, 1000, 'linear') // animate.start('left', 500, 1000, 'easeIn') // animate.start('left', 500, 1000, 'strongEaseIn') // animate.start('left', 500, 1000, 'strongEaseOut') // animate.start('left', 500, 1000, 'sineaseIn') // animate.start('left', 500, 1000, 'sineaseOut')