《JavaScript設計模式與開發實踐》模式篇(8)—— 模板方法模式

模板方法模式是一種只需使用繼承就能夠實現的很是簡單的模式。模板方法模式由兩部分結構組成,第一部分是抽象父類,第二部分是具體的實現子類。一般在抽象父類中封裝了子類的算法框架,包括實現一些公共方法以及封裝子類中全部方法的執行順序。子類經過繼承這個抽象類,也繼承了整個算法結構,而且能夠選擇重寫父類的方法。算法

故事背景

咱們如今須要沖泡一杯咖啡和一壺茶,它們的操做步驟基本上是同樣的,以下所示設計模式

泡咖啡 泡茶
把水煮沸 把水煮沸
用沸水沖泡咖啡 用沸水浸泡茶葉
把咖啡倒進杯子 把茶水倒進杯子
加糖和牛奶 加檸檬

代碼實現(繼承)

/*建立一個抽象父類來表示泡一杯飲料的整個過程。
不管是 Coffee,仍是 Tea,都被咱們用Beverage來表示*/
var Beverage = function(){};
Beverage.prototype.boilWater = function(){ 
    console.log( '把水煮沸' );
};
Beverage.prototype.brew = function(){
    throw new Error( '子類必須重寫 brew 方法' );
}; 
Beverage.prototype.pourInCup = function(){
    throw new Error( '子類必須重寫 pourInCup 方法' );
}; 
Beverage.prototype.addCondiments = function(){
    throw new Error( '子類必須重寫 addCondiments 方法' );
};
Beverage.prototype.init = function(){ 
    this.boilWater();
    this.brew();
    this.pourInCup(); 
    this.addCondiments();
};
/*建立Coffee類*/
var Coffee = function(){}; 
Coffee.prototype = new Beverage();
Coffee.prototype.brew = function(){ 
    console.log( '用沸水沖泡咖啡' );
};
Coffee.prototype.pourInCup = function(){
    console.log( '把咖啡倒進杯子' );
};
Coffee.prototype.addCondiments = function(){ 
    console.log( '加糖和牛奶' );
};
var Coffee = new Coffee(); 
Coffee.init();
/*建立Tea 類*/
var Tea = function(){};
Tea.prototype = new Beverage();
Tea.prototype.brew = function(){ 
    console.log( '用沸水浸泡茶葉' );
};
Tea.prototype.pourInCup = function(){
    console.log( '把茶倒進杯子' );
};
Tea.prototype.addCondiments = function(){ 
    console.log( '加檸檬' );
};
var tea = new Tea(); 
tea.init();
複製代碼

思考:真的須要繼承嗎?

模板方法模式中,父類封裝了子類的算法框架和方法的執行順序,子類繼承父類以後,父類通知子類執行這些方法,好萊塢原則 很好地詮釋了這種設計技巧bash

好萊塢原則

好萊塢無疑是演員的天堂,但好萊塢也有不少找不到工做的新人演員,許多新人演員在好萊 塢把簡歷遞給演藝公司以後就只有回家等待電話。有時候該演員等得不耐煩了,給演藝公司打電 話詢問狀況,演藝公司每每這樣回答:「不要來找我,我會給你打電話。」 在設計中,這樣的規則就稱爲好萊塢原則。在這一原則的指導下,咱們容許底層組件將本身 掛鉤到高層組件中,而高層組件會決定何時、以何種方式去使用這些底層組件,高層組件對 待底層組件的方式,跟演藝公司對待新人演員同樣,都是「別調用咱們,咱們會調用你」。框架

代碼重構(好萊塢原則)

var Beverage = function( param ){
    var boilWater = function(){ 
        console.log( '把水煮沸' );
    };
    var brew = param.brew || function(){  
        throw new Error( '必須傳遞 brew 方法' );
    };
    var pourInCup = param.pourInCup || function(){ 
        throw new Error( '必須傳遞 pourInCup 方法' );
    };
    var addCondiments = param.addCondiments || function(){ 
        throw new Error( '必須傳遞 addCondiments 方法' );
    };
    var F = function(){};
    F.prototype.init = function(){ 
        boilWater();
        brew();
        pourInCup();  
        addCondiments();
     };
    return F; 
};
var Coffee = Beverage({ 
    brew: function(){
        console.log( '用沸水沖泡咖啡' ); 
    },
    pourInCup: function(){
        console.log( '把咖啡倒進杯子' );
   },
   addCondiments: function(){
        console.log( '加糖和牛奶' ); 
    }
});
var Tea = Beverage({
    brew: function(){
        console.log( '用沸水浸泡茶葉' ); 
    },
    pourInCup: function(){
        console.log( '把茶倒進杯子' );
    },
    addCondiments: function(){
       console.log( '加檸檬' ); 
    }
});
var coffee = new Coffee();
coffee.init();
var tea = new Tea(); 
tea.init();
複製代碼

總結

模板方法模式是一種典型的經過封裝變化提升系統擴展性的設計模式。在傳統的面向對象語 言中,一個運用了模板方法模式的程序中,子類的方法種類和執行順序都是不變的,因此咱們把這部分邏輯抽象到父類的模板方法裏面。而子類的方法具體怎麼實現則是可變的,因而咱們把這 部分變化的邏輯封裝到子類中。經過增長新的子類,咱們便能給系統增長新的功能,並不須要改動抽象父類以及其餘子類,這也是符合開放封閉原則的。post

系列文章:

《JavaScript設計模式與開發實踐》最全知識點彙總大全ui

相關文章
相關標籤/搜索