JavaScript rule mode algorithm

Source: Internet
Author: User

Policy mode refers to the algorithm that defines some columns and encapsulates them one by one to separate the use of algorithms from the implementation of algorithms.
Js code that implements the effect of the above example using the strategy mode:

1. First encapsulate the easing algorithm of mobile nodes


/*
* Slow motion algorithm: Receives four parameters, indicating the animation disappears, the original position of the ball, the target position of the ball, and the total animation duration.
*/
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 + B;
},
StrongEaseOut: function (t, B, c, d ){
Return c * (t = t/d-1) * t + 1) + B;
},
SineaseIn: function (t, B, c, d ){
Return c * (t/= d) * t + B;
},
SineaseOut: function (t, B, c, d ){
Return c * (t = t/d-1) * t + 1) + B;
    }
};

2. HTML section

<Div style = "position: relative; border: 1px solid # ff0000; width: 560px; min-height: 30px">
<Div style = "position: absolute; background: rgba (255 ,. 3); width: 60px; line-height: 30px; "id =" div "> I am div </div>
</Div>
<Div>
<Label> <input type = "radio" name = "tween" value = "linear" checked = "checked"> linear </label>
<Label> <input type = "radio" name = "tween" value = "easeIn"> easeIn </label>
<Label> <input type = "radio" name = "tween" value = "strongEaseIn"> strongEaseIn </label>
<Label> <input type = "radio" name = "tween" value = "strongEaseOut"> strongEaseOut </label>
<Label> <input type = "radio" name = "tween" value = "sineaseIn"> sineaseIn </label>
<Label> <input type = "radio" name = "tween" value = "sineaseOut"> sineaseOut </label> <br/>
<Input type = "button" id = "btnRun" value = "run">
</Div>

3. Define a constructor to receive a parameter: the dom node to be moved

/*
* The Animate constructor receives a parameter: the dom node to be moved.
*/
Var Animate = function (dom ){
This. dom = dom; // dom node for motion
This. startTime = 0; // Animation start time
This. startPos = 0; // The position of the dom node when the animation starts, that is, the initial position of the dom.
This. endPos = 0 ;//
This. propertyName = null; // css attribute name to be changed for the dom node
This. easing = null; // easing algorithm
This. duration = null; // Animation duration
};
 

4. Start the animation.

/*
* Starts motion animation.
*/
Animate. prototype. start = function (propertyName, endPos, duration, easing ){
This. startTime = + new Date; // specifies the animation start time.
This. startPos = this. dom. getBoundingClientRect () [propertyName]; // The initial position of the dom node
This. propertyName = propertyName; // CSS attribute name to be changed for the dom node
This. endPos = endPos; // target position of the dom node
This. duration = duration; // Animation duration
This. easing = tween [easing]; // easing algorithm

// Start the animation timer
Var self = this;
Var timeId = setInterval (function (){
If (self. step () === false ){
ClearInterval (timeId );
        }
}, 20 );
};


5. Animation timer running steps, setp method, what to do for each frame of node movement

/*
* Step indicates what to do for each frame of a node. Calculates the current node position and updates CSS attribute values.
*/
Animate. prototype. step = function (){
Var t = + new Date; // get the current time
If (t> = this. startTime + this. duration) {// if the animation ends
This. update (this. endPos); // updates the CSS attributes of a node.
Return false;
    }
Var pos = this. easing (t-this. startTime, this. startPos, this. endPos-this. startPos, this. duration );
// Pos is the current node location
This. update (pos); // updates the CSS attributes of a node.
};


6. Update the CSS attribute value of a node.

/*
* Updates the CSS attribute values of nodes.
*/
Animate. prototype. update = function (pos ){
This. dom. style [this. propertyName] = pos + "px ";
};


7. Test run

/*
* Create a node to be moved
*/
Var div = document. getElementById ("div ");
Var animate = new Animate (div );
// Set the running event
Var btnRun = document. getElementById ("btnRun ");
Var radios = document. getElementsByName ("tween"); // obtain a ticket
BtnRun. onclick = function (){
For (var I = 0, lengh = radios. length; I <lengh; I ++ ){
// Search for the selected algorithm policy
If (radios [I]. checked ){
Animate. reset (); // reset node motion attributes
// Set the basic attributes of the animation
Animate. start ("left", 500,100 0, radios [I]. value );
Break;
        }
    }
};


8. reset the CSS attribute of the node to 0, reset () method

Animate. prototype. reset = function (){
// Reset to 0
This. dom. style [this. propertyName] = "0px ";
};

 
Summary of policy modes:
Advantages of the policy mode:
1. Policy modes use techniques and ideas such as combination, delegation, and polymorphism to effectively avoid multiple condition selection statements
2. The policy mode provides perfect support for the open-closed principle. It encapsulates algorithms in independent strategy, making them easy to switch, understand, and expand.
Disadvantages of Rule mode:
1. Many policy classes or policy objects will be added to the program, but it is better than stacking the logic they are responsible for in the Context.
2. When using the policy mode, you must understand all the policies to better select an appropriate policy.


A deep understanding of the rule pattern of the JavaScript design pattern

Before understanding the rule mode, let's take an example. Generally, if we want to verify the validity of data, we usually judge the validity of the data according to the swith statement, but this raises several problems, first, if you want to add more requirements, we need to modify the code again to increase the logic, and the unit test will become more and more complex. The code is as follows:

Validator = {
Validate: function (value, type ){
Switch (type ){
Case 'isnonempty ':
                        {
Return true; // NonEmpty verification result
                        }
Case 'isnumber ':
                        {
Return true; // Number verification result
Break;
                        }
Case 'isalphanum ':
                        {
Return true; // AlphaNum verification result
                        }
Default:
                        {
Return true;
                        }
                }
            }
};
// Test
Alert (validator. validate ("123", "isNonEmpty "));

So how can we avoid problems in the above code? According to the policy mode, we can encapsulate the same working code into different classes separately, and then process them through a unified policy processing class. OK, let's first define the policy processing class. The code is as follows:

Var validator = {

// All the places where the validation rule processing class can be stored will be defined separately later
Types :{},

// Error message corresponding to the verification type
Messages: [],

// Of course, the authentication type is required
Config :{},

// Exposed public verification method
// The input parameter is a key => value pair.
Validate: function (data ){

Var I, msg, type, checker, result_ OK;

// Clear all error messages
This. messages = [];

For (I in data ){
If (data. hasOwnProperty (I )){

Type = this. config [I]; // Check whether there are validation rules based on the key
Checker = this. types [type]; // gets the verification class of the verification rule

If (! Type ){
Continue; // if the verification rule does not exist, it will not be processed
                }
If (! Checker) {// if the validation rule class does not exist, an exception is thrown.
Throw {
Name: "ValidationError ",
Message: "No handler to validate type" + type
};
                }

Result_ OK = checker. validate (data [I]); // use a single verification class found for verification
If (! Result_ OK ){
Msg = "Invalid value for *" + I + "*," + checker. instructions;
This. messages. push (msg );
                }
            }
        }
Return this. hasErrors ();
},

// Helper
HasErrors: function (){
Return this. messages. length! = 0;
    }
};

The rest of the work is to define the various verification classes stored in types. Here we only give a few examples:

// Verify that the specified value is not empty
Validator. types. isNonEmpty = {
Validate: function (value ){
Return value! = "";
},
Instructions: "The input value cannot be blank"
};

// Verify whether the given value is a number
Validator. types. isNumber = {
Validate: function (value ){
Return! IsNaN (value );
},
Instructions: "The input value can only be a valid number, for example, 1, 3.14 or 2010"
};

// Verify that the given value is only a letter or number
Validator. types. isAlphaNum = {
Validate: function (value ){
Return! /[^ A-z0-9]/I. test (value );
},
Instructions: "Incoming values can only protect letters and numbers and cannot contain special characters"
};

When using this function, we first need to define the data set to be verified, and then define the rule types to be verified for each type of data. The code is as follows:

Var data = {
First_name: "Tom ",
Last_name: "Xu ",
Age: "unknown ",
Username: "TomXu"
};

Validator. config = {
First_name: 'isnonempty ',
Age: 'isnumber ',
Username: 'isalphanum'
};

Finally, the code for obtaining the verification result is simple:

Validator. validate (data );

If (validator. hasErrors ()){
Console. log (validator. messages. join ("\ n "));
}

Summary

Policy mode defines a series of algorithms. In terms of concept, all these algorithms do the same thing, but they implement different things. They can call all methods in the same way, reduces the coupling between various algorithm classes and algorithm classes.

In another aspect, it is convenient to define an algorithm class separately for unit testing, because you can perform separate tests using your own algorithms.

In practice, not only algorithms can be encapsulated, but almost any type of rules can be encapsulated. Different business rules must be applied at different times during the analysis process, it can be considered that the policy mode should be used to handle various changes.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.