Learn JavaScript Design patterns (polymorphism) _javascript techniques

Source: Internet
Author: User

The real meaning of polymorphism is that the same operation works on different objects, and can produce different interpretations and different execution results. In other words, when sending the same message to different objects, the objects give different feedback according to the message.

It's not easy to understand polymorphism literally, so let's illustrate .

The host family raised two animals, respectively, is a duck and a chicken, when the owner of their "call" order, the Duck will "quack quack" to call, and chicken will "giggle" to call. These two animals will make their own noises. They are also "animals and can make noises," but according to the instructions of the host, they emit different sounds.

In fact, it contains the idea of polymorphism. Here we have a specific introduction to the code.

1. A "polymorphic" JavaScript code

We implemented the above story in JavaScript code as follows:

var makesound = function (animal) {
 if (animal instanceof Duck) {
 console.log (' quack-quack ');
 } else if (animal instanceof chicken) {
 console.log (' giggle ');
 }
;

var Duck = function () {};
var chicken = function () {};

MakeSound (New Duck ()); Quack Quack
MakeSound (New Chicken ());//Giggle 

This code does embody "polymorphism", and when we send "call" messages to ducks and chickens, they react differently according to the message. But such "polymorphism" is not satisfactory, if later added an animal, such as a dog, apparently the dog's bark is "Wang Woo", at this time we have to change the MakeSound function, in order to let the dog also make a sound. Modifying code is always dangerous, and the more you modify it, the more likely it is that the program will go wrong, and when the species of animals become more and more numerous, makesound may become a huge function.

The idea behind polymorphism is to separate "what is done" from "Who and how to do it", that is, to separate "unchanging things" from "things That may change". In this story, animals will bark, this is the same, but different types of animals specifically how to call is variable. Isolate the invariant parts, by encapsulating the variable parts, which gives us the ability to expand the program, the program appears to be scalable, and also conforms to the open-closed principle, which is obviously more elegant and safer than adding code to the code to do the same thing.

2. The polymorphism of the object

Here is the rewrite code, first of all, we isolate the invariant parts, that is, all animals will make noises:

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

And then encapsulate the variable parts, and the polymorphism we're talking about actually refers to the polymorphism of the object:

var Duck = function () {} 

Duck.prototype.sound = function () {
 console.log (' quack ');

var chicken = function () {}

Chicken.prototype.sound = function () {
 console.log (' cluck giggle ');

MakeSound (New Duck ()); Quack Quack
MakeSound (New Chicken ());//Giggle

Now we have a "call" message to both ducks and chickens, and they respond differently after receiving the news. If a dog is added to the animal world One day, simply append some code to it, without altering the previous MakeSound function, as follows:

var Dog = function () {}

Dog.prototype.sound = function () {
 console.log (' woof ');

MakeSound (New Dog ()); Wang Woo

3. Type checking and polymorphism

Type checking is an open topic before an object polymorphism is shown, but JavaScript is a dynamic type language that does not have to be type-checked, and in order to truly understand the purpose of polymorphism, we need to turn a corner from a static type language.

The static type language is checked for type matching at compile time. In Java, for example, because of strict type checking when code is compiled, you can't give variables different types of values, and this type of checking sometimes makes the code look stiff and the code is as follows:

String str;

str = ABC; No problem 
str = 2;//Error

Now we try to change the example of ducks and chickens to Java code:

public class Duck {//Duck class public
 void MakeSound () {
 System.out.println (quack);
 }

public class Chicken {//Chicken class public
 void MakeSound () {
 System.out.println (cluck giggle);
 }


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-Quack
 }
}

We've been able to make the Ducks sound, but if we want the chickens to bark now, we're finding that it's not going to happen. Because (1) the MakeSound method of the Animalsound class is defined as a parameter that only accepts the duck type:

public class Test {public
 static void Main (String args[]) {
 Animalsound animalsound = new Animalsound ();
 Chicken Chicken = new Chicken ();
 Animalsound.makesound (chicken); Error, can only accept parameters of duck type
 }
} 

At some point, while enjoying the security of static language type checking, we feel trapped.

To solve this problem, the statically typed object-oriented language is often designed to transition upward: when assigning a value to a class variable, the type of the variable can use either the class itself or the superclass of the class. It's like when we describe a sparrow or a magpie in the sky, it usually says, "a sparrow is flying" or "a magpie is flying". But if you want to ignore their specific types, you can also say "a bird is flying."

Similarly, when the types of Duck objects and chicken objects are hidden behind the superclass animal, duck objects and chicken objects can be exchanged, which is the only way to allow the object to manifest polymorphism, and the manifestation of polymorphism is the goal of implementing many design patterns.

4. Using inheritance to get polymorphic effects

Using inheritance to get polymorphic effects is the most common means of making objects appear polymorphic. Inheritance typically includes implementing inheritance and interface inheritance. In this section, we discuss implementation inheritance, examples of interface inheritance, see Chapter 21st.

We first create a animal abstract class, and then let both duck and chicken inherit from the animal abstract class, and the assignment statements (1) and (2) in the following code are clearly set up because ducks and chickens are also animals:

Public abstract class Animal {
 abstract void makesound ();//abstract Method
} public 

class Chicken extends animal{
 p ublic void MakeSound () {
 System.out.println (cluck);
 }

public class Duck extends animal{public
 void MakeSound () {
 System.out.println (quack);
 }

Animal duck = new Duck (); (1)
Animal chicken = new Chicken ();//(2)

All that remains is for the MakeSound method of the Animalsound class to accept parameters of the animal type, rather than the specific duck type or chicken type:

public class animalsound{public
 void MakeSound (Animal Animal) {//Accept Animal type parameter
 animal.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 Quack quack
 animalsound.makesound (chicken);//Output Giggle
 }
}

5. JavaScript polymorphism

From the previous explanation we learned that the idea of polymorphism is actually separating "what to do" and "who to do it", and to achieve this, the first thing to do is to eliminate the coupling between types. If the coupling between the types is not eliminated, then we specify in the MakeSound method that the object being called is a type, and it cannot be replaced with another type. In Java, you can achieve polymorphism by going up the transition.

And the type of the JavaScript variable is variable at run time. A JavaScript object that can represent both an object of type duck and an object of chicken type, which means that the polymorphism of the JavaScript object is innate.

This innate polymorphism is not difficult to explain. JavaScript, as a dynamic type language, does not have a type-checking process at compile time, neither checks the created object type nor checks the passed parameter type. In the code example in section 2, we can either pass the Duck object as a parameter to the MakeSound function or pass the chicken object as a parameter.

Thus, the ability of an animal to make a call depends only on whether it has a MakeSound method, not on its being a type of object, and there is no degree of "type coupling" here. This is exactly what we learned from the last section of the duck type. In JavaScript, techniques such as upward transitions are not required to achieve polymorphic effects.

6. The role of polymorphism in object-oriented programming

Many people believe that polymorphism is the most important technology in object-oriented programming languages. But we are still very difficult to see this, after all, most people do not care about how the chicken is called, do not want to know how the duck is called. What does it have to do with a programmer to make a different call between a chicken and a duck under the same message?

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

The fundamental advantage of polymorphism is that you no longer have to ask the object what type you are and then invoke an action of the object based on the resulting answer-just call that behavior, and all the other polymorphic mechanisms will be arranged for you.

In other words, the most fundamental function of polymorphism is to eliminate these conditional branching statements by translating the procedural conditional branching statements into the polymorphism of objects.

Martin Fowler's words can be well explained in the following example:

In the film's filming scene, when the director shouted "Action", the protagonist began to recite lines, lighting division is responsible for lighting, the crowd behind the pretended to be shot down, the prop division to the lens of snowflakes. When you get the same message, each object knows what you're supposed to do. If you don't use the polymorphism of the object, but write the code in a process-oriented way, then the director will go to everyone before they start filming, confirm their professional division (type), and then tell them what to do. If mapped into a program, then the program will be flooded with conditional branching statements.

With the polymorphism of the object, when the director publishes the message, it does not have to consider what the objects should do when they receive the message. What the object should do is not a temporary decision, but a prior agreement and rehearsal. What each object should do, has become a method of the object, is installed inside the object, and each object is responsible for their own behavior. So these objects can work methodically and separately according to the same message.

The advantage of object-oriented design is that it distributes behavior across objects and makes them responsible for their own behavior.

Looking at a real-life example, the idea of this example is very similar to the story of animal calls.

Assuming we're going to write a map application, there are now two optional map API providers for us to access our applications. At present we choose Google Maps, Google Maps API provides a show method, responsible for the page to display the entire map. 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 Maps 

Later because of some reasons, to change the Google map to Baidu Map, in order to allow the RENDERMAP function to maintain a certain degree of elasticity, we use some conditional branch to allow the Rendermap function at the same time support Google Maps and Baidu map:

var googlemap = {
 show:function () {
 console.log (' Start rendering Google map ');
 }
;

var baidumap = {
 show:function () {
 console.log (' Start rendering of the Baidu Map ');
 }
;

var rendermap = function (type) {
 if (type = = ' Google ') {
 googlemap.show () 
 } else if (type = = ' Baidu ') {
 baidumap.show ();
 }
};

Rendermap (' Google '); Output: Start rendering Google map 
rendermap (' Baidu ');//output: Start rendering the map of Baidu 

Can be seen, although the RENDERMAP function at present to maintain a certain degree of elasticity, but this flexibility is very fragile, once you need to replace the search map, it is undoubtedly necessary to change the Rendermap function, continue to stack conditional branch statements.

Let's first abstract the same part of the program, which is to show 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 the map of Baidu 

Now look for the polymorphism in this code. When we send the "show map" message to the Google Map object and the Baidu map object, each of them will call their display method, which will produce different execution results. Object polymorphism prompts us to "do what" and "how to do" can be separated, even after the addition of a search map, the Rendermap function still does not need to make any changes, as follows:

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 way to show the map, which may not be so smooth in actual development, and can be solved with the help of adapter mode.

The above is the entire content of this article, very comprehensive, with vivid examples to help you learn polymorphism, I hope you can really have a harvest.

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.