JavaScript Design Pattern Item 1-Polymorphism

Source: Internet
Author: User
Tags scream

JavaScript Design Pattern Item 1-Polymorphism

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. 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 "polymorphism" is not satisfactory. If an animal, such as a dog, is added later, it is clear that the dog's cry is "Wang ", now, we have to change the makeSound function to make the dog scream. 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 animal types, makeSound 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.

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 without modifying the previous makeSound function, as shown below:

Var Dog = function () {} Dog. prototype. sound = function () {console. log ('wang Wangwang ') ;}; makeSound (new Dog (); // Wang Wangwang
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.

The static type language performs 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) the makeSound method of the AnimalSound class is specified to only accept Duck 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, the object-oriented language of the static type is usually designed to be able to transform upwards: when assigning values to a class variable, the type of the variable can use the class itself, you can also use the superclass of this 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, when the types of Duck objects and Chicken objects are hidden behind super-type Animal objects, Duck objects and Chicken objects can be exchanged for use, which is the only way to make objects show polymorphism, polymorphism is the goal of achieving many design patterns.

4. Use inheritance to obtain the polymorphism Effect

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.

We first create an Animal abstract class, and then let Duck and Chicken inherit from the Animal abstract class respectively. 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 is to make the makeSound method of the AnimalSound class accept the parameters of the Animal type, rather than the specific Duck type or Chicken type:

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 }}
5. JavaScript Polymorphism

We learned from the previous explanation that,The concept of polymorphism is actually to separate "what to do" from "Who to do". To achieve this, the coupling relationship between types must be eliminated first.If the coupling relationship between types is not eliminated, we specify a type in the makeSound method, 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 can represent both Duck-type objects and Chicken-type objects, 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 2, we can either pass the duck object as a parameter to the makeSound function or the chicken object as a parameter.

It can be seen that whether an animal can make a sound depends on whether it has a makeSound method, not on whether it is a type of 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.

6. The role of 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. Google map's API provides the show method to 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

Later, for some reason, Google maps will be replaced with Baidu maps. In order to make the renderMap function flexible, we will use some conditional branches to allow the renderMap function to 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, although the renderMap function currently maintains a certain degree of elasticity, this elasticity is very fragile. If you need to replace it with the search map function, you must undoubtedly change the renderMap function, 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 Google map objects and Baidu map objects respectively, we will call their show methods separately to produce different execution results. The object polymorphism reminds us that "what to do" and "how to do" can be separated. Even if the search map is added in the future, the renderMap 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 the method name provided by each map API is show, which may not be so smooth in actual development. At this time, we can solve the problem by using the adapter mode.

 

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.