架構師的工具-模板方法模式
所謂的模板就是一個重用一萬次都不會覺得有問題的代碼。 在es6中,提出了一個 ““”反引號的書寫方式–又叫做模板字符串.他最大的功能就是用來書寫模板html的.通常在js中使用模板是
"There are <b>" + basket.count + "</b> " + "items in your basket, " + "<em>" + basket.onSale + "</em> are on sale!"
像這樣使用的在ES6中引入了模板字符串的概念,只需要使用反引號進行包裹就可以: 引入的變量可以使用${}進行包裹上面可以修改為:
` //這里就是反引號,注意不是上引號,而是鍵盤esc下面那個鍵 There are <b>${basket.count}</b> items //插入指定的變量 in your basket, <em>${basket.onSale}</em> are on sale! `
上面的代碼就可以作為一串模板代碼出現。同理,在js的設計模式中,也存在模板方法模式.
模板方法模式
模板方法模式是一種基于類和繼承的模式。也是一些架構師常用的模式。
看個栗子: 小明起床
首先,小明起床,喜歡穿NB系列衣服,然后洗臉刷牙,整理書包,出門。(我這里列的是大部分人有的,如果遇見一些生活習慣不同的,那先將就下吧。:)
轉換為代碼:
var GetUp = function(){} GetUp.prototype.wear = function(){ console.log("穿NB系列的衣服"); } GetUp.prototype.brush = function(){ console.log("洗臉刷牙"); } GetUp.prototype.sortOut = function(){ console.log("整理書包"); } GetUp.prototype.out = function(){ console.log("出門"); } GetUp.prototype.init = function(){ this.wear(); this.brush(); this.sortOut(); this.out(); } var xiaoming = new GetUp(); xiaoming.init();
看上去,可以完美的表達小明的起床過程,但是我們是有情懷的人。我們想做的是,能不能抽象出一個大部分人都能用的起床模式. 有,我們可以想想。
我是一個窮逼,我家只能穿阿迪吊絲的衣服,
我現在正在找工作,我需要整理文件。
然后,洗臉刷牙這個習慣還是有的。
出門是必須的。
那么對比可以看出,只有兩個方法的內容不一樣,只需要對這兩個方法進行抽象. 相當于寫一個抽象方法,然后讓子類自己重寫。
var GetUp = function(){} GetUp.prototype.wear = function(){ //寫出方法,需要子類自己定義 throw "穿衣服需要子類自定義"; } GetUp.prototype.brush = function(){ console.log("洗臉刷牙"); } GetUp.prototype.sortOut = function(){ //子類自定義方法 throw "出門準備工作需要子類自定義"; } GetUp.prototype.out = function(){ console.log("出門"); } GetUp.prototype.init = function(){ this.wear(); this.brush(); this.sortOut(); this.out(); } var xiaoMing = new GetUp(); xiaoMing.wear = function(){ console.log("穿阿迪吊絲的衣服"); } xiaoMing.sortOut = function(){ console.log("整理文件,找工作"); } xiaoMing.init();
恩,這個模板,差不多能滿足正常人的需求。 但是,世界只有相對性,而沒有絕對性,某些有怪癖,比如,早上不洗臉刷牙.這種情況也是存在的。(我小時候,為了逃避刷牙,經常起得比我媽還早,就跑去上課). md, 怪不得我那時候同座都嫌棄我,哎,也沒有找到小時候的知己。現在腸子都悔青了。回正題。所以,要滿足這類人的需求,我們要用到一個叫做鉤子方法。其實就是一個flag.用來代表你是不是比較特殊的人。
var GetUp = function(){} GetUp.prototype.wear = function(){ //寫出方法,需要子類自己定義 throw "穿衣服需要子類自定義"; } GetUp.prototype.brush = function(){ console.log("洗臉刷牙"); } GetUp.prototype.sortOut = function(){ //子類自定義方法 throw "出門準備工作需要子類自定義"; } GetUp.prototype.out = function(){ console.log("出門"); } GetUp.prototype.needBrush = function(){ //是否需要刷牙,默認為需要 return true; } GetUp.prototype.init = function(){ this.wear(); if(this.needBrush())this.brush(); this.sortOut(); this.out(); } var xiaoMing = new GetUp(); xiaoMing.wear = function(){ console.log("穿阿迪吊絲的衣服"); } xiaoMing.sortOut = function(){ console.log("整理文件,找工作"); } xiaoMing.needBrush = function(){return false;} xiaoMing.init();
上面自定義的 “needBrush” 方法就是一個鉤子方法,用來表明,這個人是不是特立獨行的人。
其實,我們拋開鉤子的寫法,了解下他的本質,我們可以發現,一個鉤子的添加,是給你抽象類的重用性大大加分的一項,將變化的一部分,給分離出來,更大程度的讓代碼得到重用.
但是,在js中寫類,有點太過牽強。要知道js中,函數,對象才是一等公民.我們可以使用高階函數重構一個例子.
var GetUp = function(person){ var wear = person.wear || function(){ throw "穿衣服需要子類自定義"; } var brush = function(){ console.log("洗臉刷牙"); } var sortOut = person.sortOut || function(){ throw "出門準備工作需要子類自定義"; } var needBrush = person.needBrush || function(){ return true; } var out = function(){ console.log("出門"); } var init = function(){ wear(); if(needBrush()) brush(); sortOut(); out(); } return function(){ init(); } } var jimmy = { wear(){ console.log("穿鳥不拉屎的衣服"); }, sortOut(){ console.log('整理書包'); } } var _jimmy = GetUp(jimmy); _jimmy();
但是為了統一,可以將init方法返回.
var GetUp = function(person){ //... return { init } } var _jimmy = GetUp(jimmy); _jimmy.init();
這樣寫,更具有代表性,讓人能夠一眼看出來表示的意思.
模板方法的應用
模板方法的應用,其實往大的用,是給架構師來使用。比如他設計一個模板,然后交給底層程序員去實現。相當于,一個產經提一個需求,然后交給你來實現具體的內容(這兩者的區別就是,一個可以忽悠,另一個不能忽悠).
往小的用,那就不叫模板了,就是普通的策略者模式了。
說了這么多,其實,廢話+n. 模板方法在我們這個level 其實用的還是比較少了。當然也不排除,你對這個模板方法有著SM的愛好,天天套它。所以,還是一句話,不要為了模式而模式。看自己心情使用吧.
ending~