什麼是設計模式?
它到底有什麼做用?在程序員的核心競爭力——如何寫出更好的代碼中,它又扮演了什麼樣的做用?程序員
其實設計模式並非1995年誕生的那部《設計模式》纔出現,實際上,它無所不在,在此以前,可能不少那個年代的前輩,已經不知不覺中在普遍的應用它了。而首次提出設計模式概念的GoF,其實他們僅僅只作了一件事,那就是把市面上現有的優秀代碼設計方案起了個名。面試
我並不是科班出身,還記得曾經寫過的關於算法入門的一篇文章中說到,在一次面試的過程當中,我被一個冒泡排序問倒了。。。然而事實上倒是在一些邏輯處理上用過不少次,而這在接觸冒泡以前,我並不知曉。然而就表明不會嗎?不,冒泡、選擇、插入甚至什麼希爾、歸併、堆名字被叫成啥均可以無論,由於這些僅僅只是一個名字,而理解爲何這樣更好,爲何它會更快纔是核心所在。ajax
就如以前,並不懂什麼叫策略模式,但徹底不妨礙我採用對象key-value(case-solution)的碼代碼方式。不懂這些概念有什麼關係嗎?沒有,假如策略被叫作方案池,策略模式就不是策略模式了嗎?你代碼的應用方式就變了嗎?不會。它仍是它,並不會由於一個名字而改變什麼,也不是什麼高深的東西。算法
並且我相信,設計模式也不會簡簡單單隻有23種,之因此說23種,僅僅是由於當時的做者遇到過的優秀的代碼設計方式恰好有23種,而有可能你一直在採用的某種很好的寫代碼的方式,只是你不知道要怎麼表達它。設計模式
但爲何還要說設計模式呢?由於給了它起了個名字,才更利於傳播和推廣。我再也不須要由於沒文化而很是費腦力的爲你講解,我看到的那個輪廓是什麼?網絡
好了,好像有點扯遠了。框架
這裏不想講什麼設計模式6大原則,23大設計模式等等。。。這些我也不會其實= =這裏只想描述那有些模糊的輪廓。分佈式
上篇先聊3個吧,否則篇幅太長。函數
先來講一下工廠(factory)學習
相信不少框架,或一些較大型的UI庫組件庫,甚至一些功能較複雜的插件源碼中,你能夠看到不少參數傳的是factory?也就是工廠,參數確定是要語義化的,那爲何是factory?
儘管這跟工廠模式還有些差別,但這個框架,實際上就是一個大工廠,它能夠給你造炮彈,同時還能夠給你造彈藥,(如JQuery能夠給你提供query,同時還提供各種強大的拓展功能函數好比ajax、extend、proxy、each等等,這些其實都是一個個的產品,一個個被工廠生產出來的產品)
一開始,每一種類型的工廠就像社會分工大環境某一個細分領域下的工匠,它可能只能完成特定的事情。好比一個加減乘除,可能有些簡單的工廠只能完成這個事情。
// 簡單工廠模式: 廠長 => 員工 simpleFactory (type) { switch(type) { case '+' : console.log('這是加法運算'); break; case '-' : console.log('這是減法運算'); break; case '*' : console.log('這是乘法運算'); break; case '/' : console.log('這是除法運算'); break; } },
而有時候爲了使代碼更加低耦合,就不在在這裏面寫:console.log('這是加法運算')這樣的具體實現代碼,而是用一個方法包裹起來,而此類的工廠模式則叫作工廠方法模式
// 工廠方法模式: 廠長 => 主管 => 員工 factoryModule (type) { switch (type) { case '+' : this.add(); break; case '-' : this.sub(); break; case '*' : this.multip(); break; case '/' : this.division(); break; } }, add () { console.log('這是加法運算'); }, sub () { console.log('這是減法運算'); }, multip () { console.log('這是乘法運算'); }, division () { console.log('這是除法運算'); },
但有時候這個工廠很大,它變成了一個集團(已經再也不是很具體幹啥事了,它變成了抽象工廠模式),好比三星,在它的指揮中心總部(註冊中心)下屬還分了三星電子,三星網絡,三星重工,三星航空,三星物產...但這個大的集團,這個大的工廠,它實際上仍是由不少不少的小工廠組成,只不過這些工廠在總部作了註冊,作了登記,而且向它彙報財報,盈虧等等。
// 抽象工廠模式: 老闆 => 廠長 => 主管 => 員工 abstractFactory () { // 這是集團的指揮中心 this.factoryModule(); // 它可能僅僅變成了這樣;每個廠長天天來坐下工做彙報就好了,其他的無論 // ... others factoryModule }
再來看下什麼是策略?
在平時的寫代碼中,常常用到各類條件判斷對吧?此時你可能作的就是將條件一一判斷,好比if,好比三目運算符。但你沒以爲很煩嗎?
好比下面的代碼:
function judge (len) { if(len > 1) { console.log('len > 1'); } else if (len > 2) { console.log('len > 2'); } else if (len > 3) { console.log('len > 2'); } // else if ... if ... }
而這時候一種很好的方式就是採用策略模式來設計代碼,你能夠簡單理解成key-values,儘管它不只僅是這樣:
看一下代碼:
// 策略模式 Strategy () { const casePool = { case1: () => { console.log('this is the solution of the case1'); }, case2: () => { console.log('this is the solution of the case2'); } //... } // 外部調用 如:casePool['case1']() },
其實,策略模式,就是一種應對策略,一種問題-解決方案、問題-解決方案...當此類的問題不少時,一個個解決方案聚合而成的方案池。當你遇到這種問題的時候,哦,從方案池中找到對應的解決辦法,而咱們一般來講,叫作應對策略。
再來看一下觀察者模式(Observer)
登高而能望遠,這是每個登山愛好者最享受的一件事。那望遠以後呢?除了把握下方川流不息的人流車流,給予你一種一切盡在掌握的錯覺以外,還有什麼?觀察以後要幹什麼?那就是update,更新,也許你更新了對高山周圍地貌的見解,也許你明白了你爲之奮鬥半生的一套房子實際上僅僅是某一個很小的角落下某一層中的某一個小房門以後的那個小方塊,也許還有其餘。。而這就是觀察者模式。
咱們看一下觀察者的代碼結構實現:
Observer () { function observer () { this.observerList = []; } observer.prototype = { add (key) { this.observerList.push(key); }, remove (key) { return this.observerList.filter(item => item != key); }, // 誰觀察到變化了就更新誰 update (data) { this.observerList.forEach(item => { item(data); }); } } let observer1 = function (data) { console.log('我是observer1, 我觀察到數據更新了,變成:' + data); } let observer2 = function (data) { console.log('我是observer2, 我觀察到數據更新了,變成:' + data); } var o = new observer; o.add(observer1); o.add(observer2); o.update('哈哈哈'); o.update('我又更新了哦'); }
咱們常常用JavaScript來對頁面的event作監聽,一個個的addEventListener,對吧,其實這些監聽都是一個個的觀察者。
觀察者模式有很多變種,在Vue愈來愈受歡迎的今天,你也可能看到了不少這部分的內容,甚至也可能在平時的學習中,在面試中已經接觸到了,那就是訂閱-發佈模式,訂閱發佈實際上是觀察者模式的一個變種,你對某一個主題的東西作了訂閱,這個主題有新消息時,指揮中心把新消息發佈給你,而觀察者呢?它是你主動去觀察,積極去觀察那份新的變化,整個主體目標擺在那供你看,供你觀察,從而作更新。而這實際上乾的事是同樣的,輸出的結果是一致的。甚至後續的黑板模式,做爲訂閱者你還能夠參與到內容的修改、建設之中,你是分佈式的,而這在我看來這都是觀察者模式的變種。
而其實在我看來,不論是工廠,仍是策略或者是觀察者,它都是脫離了原有的個體經營,變成了聚合式的,集羣式的改變(單個的改變 => 羣體的改變),而大多時候,咱們但願的是一個羣體的改變,而不是一個單元個體都得寫一個對應的觸發函數,這樣很浪費時間,代碼也顯得很冗餘。
首發連接:https://www.imooc.com/article/284842