javascript設計模式與開發實踐(一)- 多態

PS:上一篇文章發表以後,不少朋友關注了本人的思否和掘金的博客,雖然關注的朋友還有有限,但足夠讓我把本身在技術上的問題積累分享給你們,也但願你們可以喜歡,同時能動一動手指,給一顆心(贊),博主會持續更新下去

多態

本文是《javascript設計模式與開發實踐》一書學習筆記,因書中所表述的概念簡單明瞭,故將整本書的筆記奉上,所有文章大概在20篇左右,還請朋友們持續關注javascript

動態語言類型

編程語言按照數據類型大致能夠分爲兩類,一類是靜態類型語言,另外一類是動態類型語言java

靜態類型語言,聲明任何變量或者形參都須要指定類型,例如java語言。
動態類型語言,聲明任何變量或者形參都不須要指定類型,javascript就是動態類型語言。編程

所謂動態,能夠多層面的理解,首先,聲明變量不須要指定類型,其次,在多態思想下,java中須要利用父類實現多態,而javascript就不須要,自己自帶多態屬性。設計模式

多態

熟悉java的朋友知道,java三大特徵之一就有多態,多態給java帶來了很大的靈活性,不少設計模式也是經過多態來實現,java中的多態涉及到向上轉型和向下轉型,而javascript(如下簡稱js)的"多態"就相對來講容易實現安全

咱們來看一段「多態」的js代碼編程語言

var makeSound = function(an) {
    if(an instanceof Duck) {
        console.log("嘎嘎嘎");
    } else if(an instanceof Dog) {
        console.log("汪汪汪");
    }
}

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

makeSound(new Dog());
makeSound(new Duck());

這段代碼確實體現了「多態性」,當咱們分別向鴨和雞發出「叫喚」的消息時,它們根據此 消息做出了各自不一樣的反應,可是這樣寫會有一個弊端,當更多的類型出現時,咱們要不斷的修改makeSound函數,後期makeSound函數也會變得十分巨大,這不符合良好代碼設計的規範,多態背後的思想是將「作什麼」和「誰去作以及怎樣去作」分離開來,也就是將「不變的事 物」與 「可能改變的事物」分離開來。在這個故事中,動物都會叫,這是不變的,可是不一樣類 型的動物具體怎麼叫是可變的。把不變的部分隔離出來,把可變的部分封裝起來,這給予了咱們 擴展程序的能力,程序看起來是可生長的,也是符合開放—封閉原則的,相對於修改代碼來講, 僅僅增長代碼就能完成一樣的功能,這顯然優雅和安全得多函數

首先,咱們把makeSound函數修改一下:學習

var makeSound = function(an) {
    an.speak();
}

這段代碼傳入一個對象,而後調用對象的speak函數prototype

var Duck = function(){}
Duck.prototype.sound = function(){
    console.log( '嘎嘎嘎' );
};
var Chicken = function(){}
Chicken.prototype.sound = function(){
    console.log( '咯咯咯' );
};
makeSound( new Duck() ); // 嘎嘎嘎
makeSound( new Chicken() );

如今咱們向鴨和雞都發出「叫喚」的消息,它們接到消息後分別做出了不一樣的反應。若是有 一天動物世界裏又增長了一隻狗,這時候只要簡單地追加一些代碼就能夠了,而不用改動之前的 makeSound 函數設計

類型檢查和多態

如今,咱們來進一步瞭解多態,以前說到,java的多態須要利用繼承來實現,咱們如今把動物的例子換成java代碼

public class Duck {
    public void speak(){
        System.out.println( "嘎嘎嘎" );
    }
}

public class Dog {
    public void speak(){
        System.out.println( "汪汪汪" );
    }
}

public class AnimalSpeak{
    public void makeSound(Duck duck){
        duck.speak();
    }
}

public static void main(String args[]){
    AnimalSpeak an = new AnimalSpeak();
    Duck duck = new Duck();
    an.makeSound(duck); // 輸出:嘎嘎嘎
}

如今鴨子已經順利叫出來了,可是咱們想讓狗也叫,發現不太容易實現,由於makeSound函數中,形參是Duck類型,傳入Dog類型必定會報錯,這個時候繼承就出現了,java設計思路是我先建立一個父類,具體傳入的類型由子類決定,可是makeSound函數中的形參確是父類類型,實現以下:

public abstract class Animal{
    abstract void speak(); // 抽象方法
}

public class Duck extends Animal {
    public void speak(){ // 覆寫父類中的抽象方法
        System.out.println( "嘎嘎嘎" );
    }
}

public class Dog extends Animal {
    public void speak(){ // 覆寫父類中的抽象方法
        System.out.println( "汪汪汪" );
    }
}

public class AnimalSpeak{
    public void makeSound(Animal an){
        an.speak();
    }
}

public static void main(String args[]){
    AnimalSpeak an = new AnimalSpeak();
    Animal duck = new Duck();
    Animal dog = new Dog();
    an.makeSound(duck); // 輸出:嘎嘎嘎
    an.makeSound(dog); // 輸出:汪汪汪
}

js中的多態

JavaScript 對象的多態性是與生俱來的,爲何這麼說? 仔細看看這兩個函數:

public void makeSound(Animal an){
    an.speak();
}

function(an) {
    an.speak();
}

js和java中的函數的形參是不一樣的,java定死了傳入的類型,而js是動態的,js隨即可以傳入任何類型,因此,咱們以前說js是動態類型語言,在 JavaScript 這種將函數做爲一等對象的語言中,函數自己也是對象,函數用來封裝行爲並 且可以被四處傳遞。當咱們對一些函數發出「調用」的消息時,這些函數會返回不一樣的執行結 果,這是「多態性」的一種體現,也是不少設計模式在 JavaScript 中能夠用高階函數來代替實現的緣由。

相關文章
相關標籤/搜索