摘要:嗯,模板模式應該是跟楊洋一樣帥,所以帶著這份愛慕,我們一起來看看它到底有沒有比楊洋還要帥模板方法模式是什么模板方法模式是一種只需使用繼承就可以實現的非常簡單的模式。模板方法模式由兩部分結構組成,第一部分是抽象父類,第二部分是具體實現的子類。
JavaScript-模板方法模式
模板方法是什么鬼?模板模式又是什么鬼?? 聽說它很復雜,聽說它很難,我可不可以不學啊?。刷了一會兒微博,這幾天楊洋的新電影《三生三世十里桃花》上映了,不行,我要去看,雖然閨蜜說不好看,但是,去看楊洋也是可以的,嘻嘻嘻。 嗯,模板模式應該是跟楊洋一樣帥,所以帶著這份愛慕,我們一起來看看它到底有沒有比楊洋還要帥!!
模板方法模式是什么?模板方法模式是一種只需使用繼承就可以實現的非常簡單的模式。這是它的一種定義,簡單嗎?不覺得。? ?
說到繼承,我們一定會能夠想到它肯定有父親,不然要怎么繼承。模板方法模式由兩部分結構組成,第一部分是抽象父類,第二部分是具體實現的子類。完了,又出來一個概念,抽象類?別怕,我們一一來講解。在模板方法模式中,子類實現中的相同部分被上移到父類中,而將不同的部分留給子類來實現。
首先我們先來泡一杯咖啡,一般來說,泡咖啡的步驟通常如下:
1.先把水煮沸;
2.用沸水沖泡咖啡;
3.把咖啡倒進杯子;
4.加糖和牛奶。
我們用es5來得到一杯香濃的咖啡吧:
var Coffee=function(){} Coffee.prototype.boilWater=function(){ console.log("水煮開了"); } Coffee.prototype.brewCoffeeGriends=function(){ console.log("用沸水沖泡咖啡"); } Coffee.prototype.pourInCup=function(){ console.log("把咖啡倒進杯子"); } Coffee.prototype.addSugarAndMilk=function(){ console.log("加糖和牛奶"); } // 封裝 將實現的細節交給類的內部 Coffee.prototype.init = function() { this.boilWater(); this.brewCoffeeGriends(); this.pourInCup(); this.addSugarAndMilk(); } var coffee=new Coffee(); coffee.init();
如我們所愿了,控制臺會輸出泡茶的流程,和我們寫下的一樣。
其實呢,泡茶的步驟跟泡咖啡的步驟相差不大,大致是這樣的:
1.把水煮沸;
2.用沸水浸泡茶葉;
3.把茶水倒進杯子;
4.加檸檬。
來,咱用es6來泡茶:
class Tea{ constructor(){ } boilWater(){ console.log("把水燒開"); } steepTeaBag(){ console.log("浸泡茶葉"); } pourInCup(){ console.log("倒進杯子"); } addLemon(){ console.log("加檸檬"); } init(){ this.boilWater(); this.steepTeaBag(); this.pourInCup(); this.addLemon(); } } var tea=new Tea(); tea.init();
又如我們所愿了,控制臺輸出了泡茶的流程。
思考啦!現在到了思考的時間,我們剛剛泡了一杯咖啡和一壺茶,有沒有覺得這兩個過程是大同小異的。我們能很容易的就找出他們的共同點,不同點就是原料不同嘛,茶和咖啡,我們可以把他們抽象為"飲料"哇;泡的方式不同嘛,一個是沖泡,一個是浸泡,我們可以把這個行為抽象為"泡";加入的調料也不同咯,加糖和牛奶,加檸檬,它們也可以抽象為"調料"吖。
這么一分析,是不是很清楚了吖,我們整理一下就是:
1.把水煮沸;
2.用沸水沖泡飲料;
3.把飲料倒進杯子;
4.加調料。
抽象類是不能被實例化的,一定是用來繼承的。繼承了抽象類的所有子類都將擁有跟抽象類一致的接口方法,抽象類的主要作用就是為它的子類定義這些公共接口。
通過上面分析,這里具體來說就是要把泡茶和泡咖啡的共同步驟共同點找出來,封裝到父類,也就是抽象類中,然后不同的步驟寫在子類中,也就是茶和咖啡中。抽象類既然不能被實例化,不怕啊,子類就是他的實例化。
來吧!泡飲料啦!var Beverage=function(){} Beverage.prototype.boilWater=function(){ console.log("把水煮沸"); } Beverage.prototype.brew=function(){}; Beverage.prototype.pourInCup=function(){}; Beverage.prototype.addCondiments=function(){}; // 抽象方法 Beverage.prototype.init=function(){ this.boilWater(); this.brew(); this.pourInCup(); this.addCondiments(); } var Coffee=function(){ // 將父類的構造方法拿來執行一下 Beverage.apply(this,arguments); // 就像es6的super執行 執行后this才會有對象的屬性 } Coffee.prototype=new Beverage(); var coffee=new Coffee(); coffee.init(); 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();
這里既泡了咖啡又泡了茶,是不是沒有之前那么繁瑣呢,這里的代碼可是很高級的呢。
這里用一個父類Beverage來表示Coffee和Tea,然后子類就是后面的Coffee和Tea啦,因為這里的Beverage是一個抽象的存在,需要子類來繼承它。泡飲品的流程,可以理解為一個模板模式 ,抽象類Beverage, 抽象方法init()在子類中實現。js的繼承是基于原型鏈的繼承,這里prototype就是類的原型鏈。這里由于coffee對象和tea對象的原型prototype上都沒有對應的init(),所以請求會順著原型鏈,找到父類Beverage的init()。子類尋找對應的屬性和方法的時候會順著原型鏈去查找,先找自己,沒有找到會順著去父類里面查找。
Beverage.prototype.init被稱為模板方法的原因是,該方法中封裝了子類的算法框架,它作為一個算法的模板,指導子類以何種順序去執行哪些方法。
閉包也可以實現的喲,大家對閉包不太理解的可以參考我之前的文章:作用域閉包
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 coffee=new Coffee(); coffee.init();
js 把抽象類改為配置類,param將成為Beverage函數里面的閉包函數的引用。Beverage是模板,把他變成一個可以配置的類把參數param傳進來,就玩成了配置。這里的配置就是給Beverage傳參數,也就是param。F對象規范了類的構成(流程), ?里面的四個私有變量是閉包的。當Beverage new 的時候會new 一個F, 然后就調用了閉包 ,四個私有變量也被調用。
父類里面的brew pourInCup addCondiments方法都是空的,所以子類必須重寫。父類里面的那三個方法是如果子類沒用重寫該方法,就會直接拋出一個異常那個,程序在運行時會得到一個錯誤。
模板方法模式時一種典型的通過封裝變化提高系統擴展性的設計模式。運用了模板方法模式的程序中,子類方法種類和執行順序都是不變的,但是子類的方法具體實現則是可變的。父類是個模板,子類可以添加,就增加了不同的功能。子類和父類之間也就是"堯舜禹"之間的關系,屬于同一類,沒有血緣關系。
哇,到這里帥哥就看完啦,是不是很帥,是不是很有意思,不行,我要去看我的楊洋了,拋棄我的楊洋。?
有建議或者覺得有錯誤的地方可以指出來喲,帥哥要分享,學習也要分享的。共同進步吧!?
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/84647.html
摘要:模板方法模式定義定義抽象類并且聲明一些抽象基本方法供子類實現不同邏輯,同時在抽象類中定義具體方法把抽象基本方法封裝起來,這就是模板方法模式。 近日,ofo小黃車宣布入駐法國巴黎,正式進入全球第20個國家,共享單車已然改變了我們的出行方式。就拿我自己來說,每當下班出地鐵的第一件事,以光速鎖定一輛共享單車,百米沖刺的速度搶在別人之前占領它。 而大家都是重復著同樣的動作,拿出手機開鎖、騎車、...
摘要:重構時,模板方法模式是一個經常使用的模式,把相同的代碼抽取到父類中,然后通過鉤子函數詳見后面的擴展示例約束其行為。 定義 Define the skeleton of an algorithm in an operation,deferring some steps to subclasses.TemplateMethod lets subclasses redefine certai...
摘要:也是一些架構師常用的模式。寫出方法,需要子類自己定義穿衣服需要子類自定義洗臉刷牙子類自定義方法出門準備工作需要子類自定義出門穿阿迪吊絲的衣服整理文件,找工作恩,這個模板,差不多能滿足正常人的需求。 所謂的模板就是一個重用一萬次都不會覺得有問題的代碼。 在es6中,提出了一個 ``反引號的書寫方式--又叫做模板字符串.他最大的功能就是用來書寫模板html的.通常在js中使用模板是 T...
摘要:前言本系列文章主要根據設計模式與開發實踐整理而來,其中會加入了一些自己的思考。模板方法模式由兩部分結構組成,第一部分是抽象父類,第二部分是具體的實現子類。 前言 本系列文章主要根據《JavaScript設計模式與開發實踐》整理而來,其中會加入了一些自己的思考。希望對大家有所幫助。 文章系列 js設計模式--單例模式 js設計模式--策略模式 js設計模式--代理模式 js設計模式--迭...
閱讀 1517·2021-11-18 10:02
閱讀 1657·2021-09-04 16:40
閱讀 3171·2021-09-01 10:48
閱讀 874·2019-08-30 15:55
閱讀 1853·2019-08-30 15:55
閱讀 1365·2019-08-30 13:05
閱讀 3013·2019-08-30 12:52
閱讀 1624·2019-08-30 11:24