JavaScript design patterns and development practices-JavaScript Polymorphism

Source: Internet
Author: User
Tags scream

JavaScript design patterns and development practices-JavaScript Polymorphism

"Polymorphism" is derived from polymorphism in the Greek text. The split is poly (plural) + morph (morphology) + ism, which can be literally understood as the plural form.

The actual meaning of polymorphism is: the same operation acts on different objects and can produce different interpretations and different execution results. In other words, when sending the same message to different objects, these objects will give different feedback based on the message.

It is not easy to understand polymorphism literally. The following is an example.

The master has two animals in his house: a duck and a chicken. When the master sends a "scream" command to them, the duck will scream, the chicken giggled. Both animals call each other in their own way. They are also "animals, and sound can be issued", but according to the instructions of their masters, they will each make a different cry.

In fact, it contains the idea of polymorphism. The following code gives a detailed introduction.

1.2.1 a piece of "polymorphism" JavaScript code

The above story is implemented using JavaScript Code as follows:

Var makeSound = function (animal) {if (animal instanceof Duck) {console. log ('ga ga ');} else if (animal instanceof Chicken) {console. log ('giggle ') ;}}; var Duck = function () {}; var Chicken = function () {}; makeSound (new Duck ()); // ga makeSound (new Chicken (); // giggling

This Code does reflect "polymorphism". When we send a "Call" message to the duck and chicken respectively, they make different responses based on the message. However, such a "polymorphism" is not satisfactory. If an animal, such as a dog, is added later, it is clear that the sound of the dog is "Wang". At this time, we must modify it.makeSoundFunction. It is always dangerous to modify code. The more places you modify, the higher the possibility of program errors. When there are more and more animals,makeSoundIt may become a huge function.

The idea behind polymorphism is to separate "what to do" from "Who to do and how to do, that is, the separation of "unchanged things" and "things that may change. In this story, animals are called, which remains unchanged, but how can different types of animals be called immutable. Isolate the unchanged part and encapsulate the variable part, which gives us the ability to expand the program. The program seems to be scalable and complies with the open-closed principle, compared with modifying the Code, adding only the code can accomplish the same function, which is obviously more elegant and secure.

1.2.2 object Polymorphism

The following is the modified Code. First, we isolate the unchanged part, that is, all animals will make a cry:

var makeSound = function( animal ){    animal.sound();};

Then we encapsulate the variables separately. The polymorphism we mentioned just now actually refers to the object polymorphism:

Var Duck = function () {} Duck. prototype. sound = function () {console. log ('ga ga ') ;}; var Chicken = function () {} Chicken. prototype. sound = function () {console. log ('giggling ');}; makeSound (new Duck (); // ga makeSound (new Chicken (); // giggling

Now we send a "call" message to both the duck and the chicken. They have different responses after receiving the message. If another dog is added to the animal world one day, simply append some code, instead of modifying the previousmakeSoundFunction:

Var Dog = function () {} Dog. prototype. sound = function () {console. log ('wang Wangwang ') ;}; makeSound (new Dog (); // Wang Wangwang
1.2.3 type check and Polymorphism

Type check is a non-open topic before it shows object polymorphism, but JavaScript is a dynamic type language that does not need to perform type check. In order to truly understand the purpose of polymorphism, we need to make a transition from a static language.

We have explained in section 1.1 that the static type language will perform the type matching check during compilation. Taking Java as an example, a strict type check is required during code compilation, so different types of values cannot be assigned to variables. This type check sometimes makes the code stiff. The Code is as follows:

String str; str = abc; // No problem str = 2; // Error

Now we try to replace the above example with the Java code:

Public class Duck {// Duck class public void makeSound () {System. out. println (ga) ;}} public class Chicken {// public void makeSound () {System. out. println (GIGGLING) ;}} public class AnimalSound {public void makeSound (Duck duck) {// (1) duck. makeSound () ;}} public class Test {public static void main (String args []) {AnimalSound animalSound = new AnimalSound (); Duck duck = new Duck (); animalSound. makeSound (duck); // output: ga }}

We have successfully made the duck scream, but if we want the chicken to scream now, we find this is impossible. Because (1)AnimalSoundClassmakeSoundMethod, which can only be acceptedDuckType parameters:

Public class Test {public static void main (String args []) {AnimalSound animalSound = new AnimalSound (); Chicken chicken = new Chicken (); animalSound. makeSound (chicken); // an error is returned. Only Duck-type parameters are allowed }}

In some cases, while enjoying the security of static language type checks, we also feel bound.

To solve this problem, static object-oriented languages are generally designed to beUpward Transformation: When assigning values to a class variable, the type of the variable can either use the class itself or use the super class of the class. This is like when we describe a sparrow or magpie in the sky, we usually say "a sparrow is flying" or "a magpie is flying ". However, if you want to ignore their specific types, you can also say that "A bird is flying".

Similarly, whenDuckObject andChickenAll object types are hidden in the supertypeAnimalBehind,DuckObject andChickenObjects can be exchanged for use, which is the only way to make objects show polymorphism, and the presentation of polymorphism is the goal of achieving many design patterns.

1.2.4 use inheritance to obtain Polymorphism

Using inheritance to obtain the polymorphism effect is the most common means to make objects show polymorphism. Inheritance generally includes implementation inheritance and interface inheritance. This section describes implementation inheritance. For the examples of interface inheritance, see Chapter 21st.

First, createAnimalAbstract class, and then letDuckAndChickenAre inherited fromAnimalAbstract class. In the following code, the value assignment statements at (1) and (2) are obviously true, because ducks and chickens are also animals:

Public abstract class Animal {abstract void makeSound (); // abstract method} public class Chicken extends Animal {public void makeSound () {System. out. println (GIGGLING) ;}} public class Duck extends Animal {public void makeSound () {System. out. println (ga) ;}} Animal duck = new Duck (); // (1) Animal chicken = new Chicken (); // (2)

The rest isAnimalSoundClassmakeSoundMethod acceptanceAnimalType parameter, rather than the specificDuckType orChickenType:

Public class AnimalSound {public void makeSound (Animal animal) {// accept Animal parameters. makeSound () ;}} public class Test {public static void main (String args []) {AnimalSound animalSound = new AnimalSound (); Animal duck = new Duck (); animal chicken = new Chicken (); animalSound. makeSound (duck); // output the animalSound. makeSound (chicken); // The output Giggling }}
1.2.5 JavaScript Polymorphism

We learned from the previous explanation that the multi-state idea is actually separating "what" from "who" to achieve this, in the final analysis, the coupling relationship between types must be eliminated first. If the coupling relationship between types is not eliminatedmakeSoundThe method specifies that the object for calling is of a certain type, and it cannot be replaced with another type. In Java, polymorphism can be achieved through upward transformation.

The JavaScript variable type is variable at runtime. A JavaScript Object that can representDuckType object, which can also representChickenType object, which means that the polymorphism of JavaScript objects is inherent.

This inherent polymorphism is not difficult to explain. JavaScript, as a dynamic type language, does not check the type of the created object or the passed parameter type during compilation. In the sample code in section 1.2.2makeSoundPass in the functionduckThe object can also be passed as a parameter.chickenObject as a parameter.

It can be seen that whether an animal can make a cry depends on whether it hasmakeSoundMethod, regardless of whether it is a type object. There is no "type coupling" to any extent ". This is what we learned from the duck type in the previous section. In JavaScript, technologies such as upward transformation are not required to achieve polymorphism.

Role of 1.2.6 polymorphism in Object-Oriented Programming

Many people think that polymorphism is the most important technology in object-oriented programming languages. However, it is still difficult for us to see this. After all, most people do not care about how chickens are called or how ducks are called. Let the chicken and duck send different voices under the same message. What does this have to do with programmers?

Martin Fowler wrote in refactoring: improving the design of existing code:

The most fundamental benefit of polymorphism is that you don't have to ask the object "What type are you?" And then call an action of the object based on the obtained answer-you just need to call this action, all other polymorphism mechanisms will be arranged for you.

In other words, the most fundamental role of polymorphism is to eliminate these conditional branch statements by converting procedural conditional branch statements into object polymorphism.

Martin Fowler can be well interpreted using the following example:

At the filming scene, when the director shouted "action", the main character began to recite lines, the lighting engineer was responsible for lighting, and the masses behind the actors pretended to be shot and dumped to the ground, the prop artist sprinkled snow into the camera. When getting the same message, every object knows what to do. If we don't use object polymorphism, but use process-oriented methods to write this code, it is equivalent that after the Filming starts, the Director will come to everyone every time, confirm their job division (type) and tell them what to do. If it is mapped to a program, the program will be filled with conditional branch statements.

With the object polymorphism, the Director does not have to consider what each object should do after receiving the message when publishing the message. What the object should do is not a temporary decision, but has been agreed and rehearsed in advance. What each object should do has become a method of this object, installed inside the object, and each object is responsible for their own behavior. Therefore, these objects can perform their respective work in an orderly manner based on the same message.

It is the advantage of object-oriented design to distribute behaviors in various objects and let these objects take responsibility for their own behaviors.

Let's look at another example in real development. The idea of this example is very similar to the story of animal call.

Suppose we want to write a map application. Now there are two available map API providers for us to access our own applications. Currently, we chose Google Map, which is provided by Google map APIs.showTo display the entire map on the page. The sample code is as follows:

Var googleMap = {show: function () {console. log ('start rendering google map') ;}; var renderMap = function () {googleMap. show () ;}; renderMap (); // output: Start rendering google Map

For some reason, Google maps will be replaced with Baidu maps.renderMapFunctions maintain a certain degree of elasticity. We use some conditional branches to makerenderMapFunctions Support both Google Maps and Baidu maps:

Var googleMap = {show: function () {console. log ('start rendering google map') ;}}; var baiduMap = {show: function () {console. log ('start rendering the baidu ') ;}}; var renderMap = function (type) {if (type = 'Google') {googleMap. show ();} else if (type = 'baidu') {baiduMap. show () ;}}; renderMap ('Google '); // output: Start to render the google map renderMap ('baidu'); // output: Start to render the baidu Map

As you can see, althoughrenderMapAt present, functions maintain a certain degree of elasticity, but this elasticity is very fragile. If you need to replace it with search map, you must change it.renderMapFunction, continue to pile up the condition branch statement in it.

We should first abstract the same part of the program, that is, display a map:

Var renderMap = function (map) {if (map. show instanceof Function) {map. show () ;}}; renderMap (googleMap); // output: Start rendering google map renderMap (baiduMap); // output: Start rendering baidu Map

Now let's look for the polymorphism in this Code. When we send a "Map Display" message to the Google Maps object and Baidu map object respectively, they will callshowMethod to generate different execution results. The object polymorphism reminds us that "what to do" and "how to do" can be separated, even if a search map is added in the future,renderMapThe function still does not need to be changed, as shown below:

Var sosoMap = {show: function () {console. log ('start rendering soso map') ;}}; renderMap (sosoMap); // output: Start rendering soso Map

In this example, we assume that each map API provides a method namedshowIn actual development, it may not be so smooth. In this case, you can use the adapter mode to solve the problem.

1.2.7 design pattern and Polymorphism

The sub-title of "Design Patterns" by GoF is "the basis for reusable object-oriented software ". From the perspective of object-oriented design, this book extracts some reusable object-oriented design skills through repeated use of encapsulation, inheritance, polymorphism, and combination technologies. Polymorphism is the most important among them, and the implementation of most design patterns is inseparable from the idea of polymorphism.

In command mode 1, the request is encapsulated in some command objects, which allows the caller and receiver of the command to be completely decoupled.executeMethods, different commands will do different things, and thus different execution results will be generated. The process of doing these things has long been encapsulated inside the command object. As the customer who calls the command, there is no need to worry about the specific process of command execution.

In composite mode 2, polymorphism allows the customer to ignore the difference between the composite object and the leaf node object, which is the biggest role of composite mode. When the composite object and leaf node object send the same message, they will do what they should do, and the composite object will forward the message to the leaf node object below, the leaf node object will provide real feedback on these messages.

In policy Mode 3, Context does not have the ability to execute algorithms, but delegates this responsibility to a policy object. Algorithms for each policy object have been encapsulated in the object. When we send "computing" messages to these policy objects, they return different computing results.

1. See chapter 9th "command mode" 2. See Chapter 10th "Combination Mode" 3. See chapter 5th "rule mode"

In JavaScript, a language that uses a function as a first-class object, a function itself is also an object. A function is used to encapsulate behavior and can be passed everywhere. When we send a "call" message to some functions, these functions return different execution results, which is a manifestation of "polymorphism, this is also why many design patterns can be replaced by higher-order functions in JavaScript.

 

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.