javascript的模板方法模式

模板方法是一種只需要使用繼承就可以實現(xiàn)的非常簡單的模式
模板方法由兩部分組成,一是抽象的父類,二是具體實現(xiàn)的子類。通常在抽象父類中封裝了子類的算法框架,包括實現(xiàn)一些公共方法以及封裝子類中所有方法的執(zhí)行順序。

參考《javascript模式設(shè)計與開發(fā)實踐》第11章

這個模式方法很有意思,在使用之前需要有一個抽象的額過程,是對類似的生產(chǎn)過程的具體細節(jié)的理解,找出流程中的共同點作為抽象的父類。
咖啡和茶的沖泡過程

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

把泡咖啡和泡茶的不同點標(biāo)示出來,剩下的部分就是共同的部分

  • [ ] 原料不同,一個是咖啡,一個是茶。抽象為飲料
  • [ ] 泡的方式不同,一個是泡,一個是浸泡。統(tǒng)一抽象為泡
  • [ ] 加入的調(diào)味品不同,一個是糖和牛奶,一個是檸檬。抽象為調(diào)料
    整個沖泡飲料的過程就抽象為下面的流程
  1. 把水煮沸
  2. 用沸水沖泡飲料
  3. 把飲料倒進被子
  4. 加調(diào)料

抽象的父類的代碼

 var Beverage = function(){}; 
    Beverage.prototype.boilWater = function(){
        console.log( '把水煮沸' );
    };

    Beverage.prototype.brew = function(){}; // 空方法,應(yīng)該由子類重寫
    Beverage.prototype.pourInCup = function(){}; // 空方法,應(yīng)該由子類重寫
    Beverage.prototype.addCondiments = function(){}; // 空方法,應(yīng)該由子類重寫
    Beverage.prototype.init = function(){//定義子類的函數(shù)執(zhí)行順序
        this.boilWater();
        this.brew();
        this.pourInCup();
        this.addCondiments();
    };

有了父類的模板,在煮茶是就依照父類的模板來使用,通用部分不動,特殊的地方重寫父類的方法

茶葉子類繼承父類的模板

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(); //依照父類的方法執(zhí)行順序來執(zhí)行

//由于javascript的對象原型繼承鏈的方式和java的繼承是完全不同的,這里代碼結(jié)構(gòu)和java類似,但是里面的機制是不同的

```
鉤子方法
  1. 把水煮沸
  2. 用沸水沖泡飲料
  3. 把飲料倒進被子
  4. 加調(diào)料

上面是一般的沖調(diào)飲料的流程,但是可能會有特殊情況,比如有的人可能不會加調(diào)料。遇到這種情況需要使用鉤子方法來在隔離有變化的步驟

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.customerWantsCondiments = function(){
        return true; // 默認需要調(diào)料
    };
    Beverage.prototype.init = function(){
        this.boilWater();
        this.brew();
        this.pourInCup();
    if ( this.customerWantsCondiments() ){ // 如果掛鉤返回true,則需要調(diào)料
        this.addCondiments(); //第四步就變?yōu)榭蛇x的方法了
    }
};

實例化沖泡咖啡的實例

 var CoffeeWithHook = function(){};
 CoffeeWithHook.prototype = new Beverage();
CoffeeWithHook.prototype.brew = function(){
    console.log( '用沸水沖泡咖啡' );
};
CoffeeWithHook.prototype.pourInCup = function(){
    console.log( '把咖啡倒進杯子' );
};
CoffeeWithHook.prototype.addCondiments = function(){
    console.log( '加糖和牛奶' );
};
CoffeeWithHook.prototype.customerWantsCondiments = function(){
    return window.confirm( '請問需要調(diào)料嗎?' );//對顧客選擇的判斷條件
};
var coffeeWithHook = new CoffeeWithHook();

模板方法通過封裝變化提高系統(tǒng)擴展能力。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容