關(guān)于我們
書單推薦
新書推薦
|
JavaScript設(shè)計模式與開發(fā)實踐
《JavaScript設(shè)計模式與開發(fā)實踐》在尊重《設(shè)計模式》原意的同時,針對JavaScript語言特性全面介紹了更適合JavaScript程序員的了16個常用的設(shè)計模式,講解了JavaScript面向?qū)ο蠛秃瘮?shù)式編程方面的基礎(chǔ)知識,介紹了面向?qū)ο蟮脑O(shè)計原則及其在設(shè)計模式中的體現(xiàn),還分享了面向?qū)ο缶幊碳记珊腿粘i_發(fā)中的代碼重構(gòu)!禞avaScript設(shè)計模式與開發(fā)實踐》將教會你如何把經(jīng)典的設(shè)計模式應(yīng)用到JavaScript語言中,編寫出優(yōu)美高效、結(jié)構(gòu)化和可維護的代碼。
適讀人群 :適合初中級Web前端開發(fā)人員閱讀。
騰訊前端Alloy Team團隊出品,資深前端工程師曾探力作 全面涵蓋專門針對JavaScript的16個設(shè)計模式 深入剖析面向?qū)ο笤O(shè)計原則、編程技巧及代碼重構(gòu) 設(shè)計模式是軟件設(shè)計中經(jīng)過了大量實際項目驗證的可復(fù)用的優(yōu)秀解決方案,它有助于程序員寫出可復(fù)用和可維護性高的程序。許多優(yōu)秀的JavaScript開源框架都運用了不少設(shè)計模式,越來越多的程序員從設(shè)計模式中獲益,也許是改善了自己編寫的某個軟件,也許是更好地理解了面向?qū)ο蟮木幊趟枷搿o論如何,系統(tǒng)地學(xué)習(xí)設(shè)計模式都會令你受益匪淺。
《設(shè)計模式》一書自1995年成書一來,一直是程序員談?wù)摰摹案叨恕痹掝}之一。許多程序員從設(shè)計模式中學(xué)到了設(shè)計軟件的靈感,或者找到了問題的解決方案。在社區(qū)中,既有人對模式無比崇拜,也有人對模式充滿誤解。有些程序員把設(shè)計模式視為圣經(jīng),唯模式至上;有些人卻認為設(shè)計模式只在C++或者Java中有用武之地,JavaScript這種動態(tài)語言根本就沒有設(shè)計模式一說。
那么,在進入設(shè)計模式的學(xué)習(xí)之前,我們最好還是從模式的起源說起,分別聽聽這些不同的聲音。 設(shè)計模式并非是軟件開發(fā)的專業(yè)術(shù)語。實際上,“模式”最早誕生于建筑學(xué)。20世紀70年代,哈佛大學(xué)建筑學(xué)博士Christopher Alexander和他的研究團隊花了約20年的時間,研究了為解決同一個問題而設(shè)計出的不同建筑結(jié)構(gòu),從中發(fā)現(xiàn)了那些高質(zhì)量設(shè)計中的相似性,并且用“模式”來指代這種相似性。 受Christopher Alexander工作的啟發(fā),Erich Gamma、Richard Helm、Ralph Johnson、John Vlissides四人(人稱Gang Of Four ,GoF)把這種“模式”觀點應(yīng)用于面向?qū)ο蟮能浖O(shè)計中,并且總結(jié)了23種常見的軟件開發(fā)設(shè)計模式,錄入《設(shè)計模式:可復(fù)用面向?qū)ο筌浖幕A(chǔ)》一書。 設(shè)計模式的定義是:在面向?qū)ο筌浖O(shè)計過程中針對特定問題的簡潔而優(yōu)雅的解決方案。 通俗一點說,設(shè)計模式是在某種場合下對某個問題的一種解決方案。如果再通俗一點說,設(shè)計模式就是給面向?qū)ο筌浖_發(fā)中的一些好的設(shè)計取個名字。 GoF成員之一 John Vlissides在他的另一本關(guān)于設(shè)計模式的著作《設(shè)計模式沉思錄》中寫過這樣一段話: 設(shè)想有一個電子愛好者,雖然他沒有經(jīng)過正規(guī)的培訓(xùn),但是卻日積月累地設(shè)計并制造出許多有用的電子設(shè)備:業(yè)余無線電、蓋革計數(shù)器、報警器等。有一天這個愛好者決定重新回到學(xué)校去攻讀電子學(xué)學(xué)位,來讓自己的才能得到真實的認可。隨著課程的展開,這個愛好者突然發(fā)現(xiàn)課程內(nèi)容都似曾相識。似曾相識的并不是術(shù)語或者表述的方式,而是背后的概念。這個愛好者不斷學(xué)到一些名稱和原理,雖然這些名稱和原理原來他不知道,但事實上他多年來一直都在使用。整個過程只不過是一個接一個的頓悟。 軟件開發(fā)中的設(shè)計也是如此。這些“好的設(shè)計”并不是GoF發(fā)明的,而是早已存在于軟件開發(fā)中。一個稍有經(jīng)驗的程序員也許在不知不覺中數(shù)次使用過這些設(shè)計模式。GoF最大的功績是把這些“好的設(shè)計”從浩瀚的面向?qū)ο笫澜缰刑暨x出來,并且給予它們一個好聽又好記的名字。 那么,給模式一個名字有什么意義呢?上述故事中的電子愛好者在未進入學(xué)校之前,一點都不知道這些關(guān)于電器的概念有一些特定的名稱,但這不妨礙他制造出一些電子設(shè)備。 實際上給“模式”取名的意義非常重要。人類可以走到生物鏈頂端的前兩個原因分別是會“使用名字”和“使用工具”。在軟件設(shè)計中,一個好的設(shè)計方案有了名字之后,才能被更好地傳播,人們才有更多的機會去分享和學(xué)習(xí)它們。 也許這個小故事可以說明名字對于模式的重要性:假設(shè)你是一名足球教練,正在球場邊指揮一場足球賽。通過一段時間的觀察后,發(fā)現(xiàn)對方的后衛(wèi)技術(shù)精湛,身體強壯,但邊后衛(wèi)速度較慢,中后衛(wèi)身高和頭球都非常一般。于是你在場邊大聲指揮隊員:“用速度突破對方邊后衛(wèi)之后,往球門方向踢出高球,中路接應(yīng)隊員搶點頭球攻門。” 在機會稍縱即逝的足球場上,教練這樣費盡口舌地指揮隊員比賽無疑是荒謬的。實際上這種戰(zhàn)術(shù)有一個名字叫作“下底傳中”。正因為戰(zhàn)術(shù)有了對應(yīng)的名字,在球場上教練可以很方便地和球員交流!跋碌讉髦小边@種戰(zhàn)術(shù)即是足球場上的一種“模式”。 在軟件設(shè)計中亦是如此。我們都知道設(shè)計經(jīng)驗非常重要。也許我們都有過這種感覺:這個問題發(fā)生的場景似曾相識,以前我遇到并解決過這個問題,但是我不知道怎么跟別人去描述它。我們非常希望給這個問題出現(xiàn)的場景和解決方案取一個統(tǒng)一的名字,當(dāng)別人聽到這個名字的時候,便知道我想表達什么。比如一個JavaScript新手今天學(xué)會了編寫each函數(shù),each函數(shù)用來迭代一個數(shù)組。他很難想到這個each函數(shù)其實就是迭代器模式。于是他向別人描述這個函數(shù)結(jié)構(gòu)和意圖的時候會遇到困難,而一旦大家對迭代器模式這個名字達成了共識,剩下的交流便是自然而然的事情。 學(xué)習(xí)模式的作用 小說家很少從頭開始設(shè)計劇情,足球教練也很少從頭開始發(fā)明戰(zhàn)術(shù),他們總是沿襲一些已經(jīng)存在的模式。當(dāng)足球教練看到對方邊后衛(wèi)速度慢,中后衛(wèi)身高矮時,自然會想到“下底傳中”這種模式。 同樣,在軟件設(shè)計中,模式是一些經(jīng)過了大量實際項目驗證的優(yōu)秀解決方案。熟悉這些模式的程序員,對某些模式的理解也許形成了條件反射。當(dāng)合適的場景出現(xiàn)時,他們可以很快地找到某種模式作為解決方案。 比如,當(dāng)他們看到系統(tǒng)中存在一些大量的相似對象,這些對象給系統(tǒng)的內(nèi)存帶來了較大的負擔(dān)。如果他們熟悉享元模式,那么第一時間就可以想到用享元模式來優(yōu)化這個系統(tǒng)。再比如,系統(tǒng)中某個接口的結(jié)構(gòu)已經(jīng)不能符合目前的需求,但他們又不想去改動這個被灰塵遮住的老接口,一個熟悉模式的程序員將很快地找到適配器模式來解決這個問題。 如果我們還沒有學(xué)習(xí)全部的模式,當(dāng)遇到一個問題時,我們冥冥之中覺得這個問題出現(xiàn)的幾率很高,說不定別人也遇到過同樣的問題,并且已經(jīng)把它整理成了模式,提供了一種通用的解決方案。這時候去翻翻《設(shè)計模式》這本書也許就會有意外的收獲。 模式在不同語言之間的區(qū)別 《設(shè)計模式》一書的副標(biāo)題是“可復(fù)用面向?qū)ο筌浖幕A(chǔ)”。《設(shè)計模式》這本書完全是從面向?qū)ο笤O(shè)計的角度出發(fā)的,通過對封裝、繼承、多態(tài)、組合等技術(shù)的反復(fù)使用,提煉出一些可重復(fù)使用的面向?qū)ο笤O(shè)計技巧。所以有一種說法是設(shè)計模式僅僅是就面向?qū)ο蟮恼Z言而言的。 《設(shè)計模式》最初講的確實是靜態(tài)類型語言中的設(shè)計模式,原書大部分代碼由C++寫成,但設(shè)計模式實際上是解決某些問題的一種思想,與具體使用的語言無關(guān)。模式社區(qū)和語言一直都在發(fā)展,如今,除了主流的面向?qū)ο笳Z言,函數(shù)式語言的發(fā)展也非常迅猛。在函數(shù)式或者其他編程范型的語言中,設(shè)計模式依然存在。 人類飛上天空需要借助飛機等工具,而鳥兒天生就有翅膀。在Dota游戲里,牛頭人的人生目標(biāo)是買一把跳刀(跳刀可以使用跳躍技能),而敵法師天生就有跳躍技能。因為語言的不同,一些設(shè)計模式在另外一些語言中的實現(xiàn)也許跟我們在《設(shè)計模式》一書中看到的大相徑庭,這一點也不令人意外。 Google的研究總監(jiān)Peter Norvig早在1996年一篇名為“動態(tài)語言設(shè)計模式”的演講中,就指出了GoF所提出的23種設(shè)計模式,其中有16種在Lisp語言中已經(jīng)是天然的實現(xiàn)。比如,Command模式在Java中需要一個命令類,一個接收者類,一個調(diào)用者類。Command模式把運算塊封裝在命令對象的方法內(nèi),成為該對象的行為,并把命令對象四處傳遞。但在Lisp或者JavaScript這些把函數(shù)當(dāng)作一等對象的語言中,函數(shù)便能封裝運算塊,并且函數(shù)可以被當(dāng)成對象一樣四處傳遞,這樣一來,命令模式在Lisp或者JavaScript中就成為了一種隱形的模式。 在Java這種靜態(tài)編譯型語言中,無法動態(tài)地給已存在的對象添加職責(zé),所以一般通過包裝類的方式來實現(xiàn)裝飾者模式。但在JavaScript這種動態(tài)解釋型語言中,給對象動態(tài)添加職責(zé)是再簡單不過的事情。這就造成了JavaScript語言的裝飾者模式不再關(guān)注于給對象動態(tài)添加職責(zé),而是關(guān)注于給函數(shù)動態(tài)添加職責(zé)。 設(shè)計模式的適用性 設(shè)計模式被一些人認為只是夸夸其談的東西,這些人認為設(shè)計模式并沒有多大用途。畢竟我們用普通的方法就能解決的問題,使用設(shè)計模式可能會增加復(fù)雜度,或帶來一些額外的代碼。如果對一些設(shè)計模式使用不當(dāng),事情還可能變得更糟。 從某些角度來看,設(shè)計模式確實有可能帶來代碼量的增加,或許也會把系統(tǒng)的邏輯搞得更復(fù)雜。但軟件開發(fā)的成本并非全部在開發(fā)階段,設(shè)計模式的作用是讓人們寫出可復(fù)用和可維護性高的程序。假設(shè)有一個空房間,我們要日復(fù)一日地往里面放一些東西。最簡單的辦法當(dāng)然是把這些東西直接扔進去,但是時間久了,就會發(fā)現(xiàn)很難從這個房子里找到自己想要的東西,要調(diào)整某幾樣?xùn)|西的位置也不容易。所以在房間里做一些柜子也許是個更好的選擇,雖然柜子會增加我們的成本,但它可以在維護階段為我們帶來好處。使用這些柜子存放東西的規(guī)則,或許就是一種模式。 所有設(shè)計模式的實現(xiàn)都遵循一條原則,即“找出程序中變化的地方,并將變化封裝起來”。一個程序的設(shè)計總是可以分為可變的部分和不變的部分。當(dāng)我們找出可變的部分,并且把這些部分封裝起來,那么剩下的就是不變和穩(wěn)定的部分。這些不變和穩(wěn)定的部分是非常容易復(fù)用的。這也是設(shè)計模式為什么描寫的是可復(fù)用面向?qū)ο筌浖A(chǔ)的原因。 設(shè)計模式被人誤解的一個重要原因是人們對它的誤用和濫用,比如將一些模式用在了錯誤的場景中,或者說在不該使用模式的地方刻意使用模式。特別是初學(xué)者在剛學(xué)會使用一個模式時,恨不得把所有的代碼都用這個模式來實現(xiàn)。錘子理論在這里體現(xiàn)得很明顯:當(dāng)我們有了一把錘子,看什么都是釘子。拿足球比賽的例子來說,我們的目標(biāo)只是進球,“下底傳中”這種“模式”僅僅是達到進球目標(biāo)的一種手段。當(dāng)我們面臨密集防守時,下底傳中或許是一種好的選擇;但如果我們的球員獲得了一個直接面對對方守門員的單刀機會,那么是否還要把球先傳向邊路隊友,再由邊路隊友來一個邊路傳中呢?答案是顯而易見的,模式應(yīng)該用在正確的地方。而哪些才算正確的地方,只有在我們深刻理解了模式的意圖之后,再結(jié)合項目的實際場景才會知道。 分辨模式的關(guān)鍵是意圖而不是結(jié)構(gòu) 在設(shè)計模式的學(xué)習(xí)中,有人經(jīng)常發(fā)出這樣的疑問:代理模式和裝飾者模式,策略模式和狀態(tài)模式,策略模式和智能命令模式,這些模式的類圖看起來幾乎一模一樣,它們到底有什么區(qū)別? 實際上這種情況是普遍存在的,許多模式的類圖看起來都差不多,模式只有放在具體的環(huán)境下才有意義。比如我們的手機,把它當(dāng)電話的時候,它就是電話;把它當(dāng)鬧鐘的時候,它就是鬧鐘;用它玩游戲的時候,它就是游戲機。我看到有人手中拿著iPhone18,但那實際上可能只是一個吹風(fēng)機。有很多模式的類圖和結(jié)構(gòu)確實很相似,但這不太重要,辨別模式的關(guān)鍵是這個模式出現(xiàn)的場景,以及為我們解決了什么問題。 對JavaScript設(shè)計模式的誤解 雖然JavaScript是一門完全面向?qū)ο蟮恼Z言,但在很長一段時間內(nèi),JavaScript在人們的印象中只是用來驗證表單,或者完成一些簡單動畫特效的腳本語言。在JavaScript語言上運用設(shè)計模式難免顯得小題大做。但目前JavaScript已成為最流行的語言之一,在許多大型Web項目中,JavaScript代碼的數(shù)量已經(jīng)非常多了。我們絕對有必要把一些優(yōu)秀的設(shè)計模式借鑒到JavaScript這門語言中。許多優(yōu)秀的JavaScript開源框架也運用了不少設(shè)計模式。 J avaScript設(shè)計模式的社區(qū)目前還幾乎是一片荒漠。網(wǎng)絡(luò)上有一些討論JavaScript設(shè)計模式的資料和文章,但這些資料和文章大多都存在兩個問題。 第一個問題是習(xí)慣把靜態(tài)類型語言的設(shè)計模式照搬到JavaScript中,比如有人為了模擬JavaScript版本的工廠方法(Factory Method)模式,而生硬地把創(chuàng)建對象的步驟延遲到子類中。實際上,在Java等靜態(tài)類型語言中,讓子類來“決定”創(chuàng)建何種對象的原因是為了讓程序迎合依賴倒置原則(DIP)。在這些語言中創(chuàng)建對象時,先解開對象類型之間的耦合關(guān)系非常重要,這樣才有機會在將來讓對象表現(xiàn)出多態(tài)性。 而在JavaScript這種類型模糊的語言中,對象多態(tài)性是天生的,一個變量既可以指向一個類,又可以隨時指向另外一個類。JavaScript不存在類型耦合的問題,自然也沒有必要刻意去把對象“延遲”到子類創(chuàng)建,也就是說,JavaScript實際上是不需要工廠方法模式的。模式的存在首先是能為我們解決什么問題,這種牽強的模擬只會讓人覺得設(shè)計模式既難懂又沒什么用處。 另一個問題是習(xí)慣根據(jù)模式的名字去臆測該模式的一切。比如命令模式本意是把請求封裝到對象中,利用命令模式可以解開請求發(fā)送者和請求接受者之間的耦合關(guān)系。但命令模式經(jīng)常被人誤解為只是一個名為execute的普通方法調(diào)用。這個方法除了叫作execute之外,其實并沒有看出其他用處。所以許多人會誤會命令模式的意圖,以為它其實沒什么用處,從而聯(lián)想到其他設(shè)計模式也沒有用處。 這些誤解都影響了設(shè)計模式在JavaScript語言中的發(fā)展。 模式的發(fā)展 前面說過,模式的社區(qū)一直在發(fā)展。GoF在1995年提出了23種設(shè)計模式。但模式不僅僅局限于這23種。在近20年的時間里,也許有更多的模式已經(jīng)被人發(fā)現(xiàn)并總結(jié)了出來。比如一些JavaScript圖書中會提到模塊模式、沙箱模式等。這些“模式”能否被世人公認并流傳下來,還有待時間驗證。不過某種解決方案要成為一種模式,還是有幾個原則要遵守的。這幾個原則即是“再現(xiàn)”“教學(xué)”和“能夠以一個名字來描述這種模式”。 不管怎樣,在一些模式被公認并流行起來之前,需要慎重地冠之以某種模式的名稱。否則模式也許很容易泛濫,導(dǎo)致人人都在發(fā)明模式,這反而增加了交流的難度。說不準(zhǔn)哪天我們就能聽到有人說全局變量模式、加模式、減模式等。 在《設(shè)計模式》出版后的近20年里,也出現(xiàn)了另外一批講述設(shè)計模式的優(yōu)秀讀物。其中許多都獲得過Jolt大獎。數(shù)不清的程序員從設(shè)計模式中獲益,也許是改善了自己編寫的某個軟件,也許是從設(shè)計模式的學(xué)習(xí)中更好地理解了面向?qū)ο缶幊趟枷。無論如何,相信對我們這些大多數(shù)的普通程序員來說,系統(tǒng)地學(xué)習(xí)設(shè)計模式并沒有壞處,相反,你會在模式的學(xué)習(xí)過程中受益匪淺。
曾探,2007年畢業(yè)于吉林大學(xué)軟件學(xué)院。就職于國內(nèi)知名前端團隊騰訊AlloyTeam,高級工程師。曾參與WebQQ、QQ群、Q+開發(fā)者網(wǎng)站、微云、QQ興趣部落等大型前端項目的開發(fā)。有過Java、Python和JavaScript的開發(fā)經(jīng)驗,業(yè)余作品有HTML5版街頭霸王等。平時喜歡電影和音樂,業(yè)余時間也是一名健身教練。
第一部分 基礎(chǔ)知識
第1章 面向?qū)ο蟮腏avaScript 1.1 動態(tài)類型語言和鴨子類型 1.2 多態(tài) 1.3 封裝 1.4 原型模式和基于原型繼承的JavaScript對象系統(tǒng) 第2章 this、call和apply 2.1 this 2.2 call和apply 第3章 閉包和高階函數(shù) 3.1 閉包 3.2 高階函數(shù) 3.3 小結(jié) 第二部分 設(shè)計模式 第4章 單例模式 4.1 實現(xiàn)單例模式 4.2 透明的單例模式 4.3 用代理實現(xiàn)單例模式 4.4 JavaScript中的單例模式 4.5 惰性單例 4.6 通用的惰性單例 4.7 小結(jié) 第5章 策略模式 5.1 使用策略模式計算獎金 5.2 JavaScript 版本的策略模式 5.3 多態(tài)在策略模式中的體現(xiàn) 5.4 使用策略模式實現(xiàn)緩動動畫 5.5 更廣義的"算法" 5.6 表單校驗 5.7 策略模式的優(yōu)缺點 5.8 一等函數(shù)對象與策略模式 5.9 小結(jié) 第6章 代理模式 6.1 第一個例子--小明追MM的故事 6.2 保護代理和虛擬代理 6.3 虛擬代理實現(xiàn)圖片預(yù)加載 6.4 代理的意義 6.5 代理和本體接口的一致性 6.6 虛擬代理合并HTTP 請求 6.7 虛擬代理在惰性加載中的應(yīng)用 6.8 緩存代理 6.9 用高階函數(shù)動態(tài)創(chuàng)建代理 6.10 其他代理模式 6.11 小結(jié) 第7章 迭代器模式 7.1 jQuery 中的迭代器 7.2 實現(xiàn)自己的迭代器 7.3 內(nèi)部迭代器和外部迭代器 7.4 迭代類數(shù)組對象和字面量對象 7.5 倒序迭代器 7.6 中止迭代器 7.7 迭代器模式的應(yīng)用舉例 7.8 小結(jié) 第8章 發(fā)布-訂閱模式 8.1 現(xiàn)實中的發(fā)布-訂閱模式 8.2 發(fā)布-訂閱模式的作用 8.3 DOM 事件 8.4 自定義事件 8.5 發(fā)布-訂閱模式的通用實現(xiàn) 8.6 取消訂閱的事件 8.7 真實的例子--網(wǎng)站登錄 8.8 全局的發(fā)布-訂閱對象 8.9 模塊間通信 8.10 必須先訂閱再發(fā)布嗎 8.11 全局事件的命名沖突 8.12 JavaScript實現(xiàn)發(fā)布-訂閱模式的便利性 8.13 小結(jié) 第9章 命令模式 9.1 命令模式的用途 9.2 命令模式的例子--菜單程序 9.3 JavaScript中的命令模式 9.4 撤銷命令 9.5 撤消和重做 9.6 命令隊列 9.7 宏命令 9.8 智能命令與傻瓜命令 9.9 小結(jié) 第10章 組合模式 10.1 回顧宏命令 10.2 組合模式的用途 10.3 請求在樹中傳遞的過程 10.4 更強大的宏命令 10.5 抽象類在組合模式中的作用 10.6 透明性帶來的安全問題 10.7 組合模式的例子--掃描文件夾 10.8 一些值得注意的地方 10.9 引用父對象 10.10 何時使用組合模式 10.11 小結(jié) 第11章 模板方法模式 11.1 模板方法模式的定義和組成 11.2 第一個例子--Coffee or Tea 11.3 抽象類 11.4 模板方法模式的使用場景 11.5 鉤子方法 11.6 好萊塢原則 11.7 真的需要"繼承"嗎 11.8 小結(jié) 第12章 享元模式 12.1 初識享元模式 12.2 內(nèi)部狀態(tài)與外部狀態(tài) 12.3 享元模式的通用結(jié)構(gòu) 12.4 文件上傳的例子 12.5 享元模式的適用性 12.6 再談內(nèi)部狀態(tài)和外部狀態(tài) 12.7 對象池 12.8 小結(jié) 第13章 職責(zé)鏈模式 13.1 現(xiàn)實中的職責(zé)鏈模式 13.2 實際開發(fā)中的職責(zé)鏈模式 13.3 用職責(zé)鏈模式重構(gòu)代碼 13.4 靈活可拆分的職責(zé)鏈節(jié)點 13.5 異步的職責(zé)鏈 13.6 職責(zé)鏈模式的優(yōu)缺點 13.7 用AOP 實現(xiàn)職責(zé)鏈 13.8 用職責(zé)鏈模式獲取文件上傳對象 13.9 小結(jié) 第14章 中介者模式 14.1 現(xiàn)實中的中介者 14.2 中介者模式的例子--泡泡堂游戲 14.3 中介者模式的例子--購買商品 14.4 小結(jié) 第15章 裝飾者模式 15.1 模擬傳統(tǒng)面向?qū)ο笳Z言的裝飾者模式 15.2 裝飾者也是包裝器 15.3 回到JavaScript 的裝飾者 15.4 裝飾函數(shù) 15.5 用AOP 裝飾函數(shù) 15.6 AOP 的應(yīng)用實例 15.7 裝飾者模式和代理模式 15.8 小結(jié) 第16章 狀態(tài)模式 16.1 初識狀態(tài)模式 16.2 狀態(tài)模式的定義 16.3 狀態(tài)模式的通用結(jié)構(gòu) 16.4 缺少抽象類的變通方式 16.5 另一個狀態(tài)模式示例--文件上傳 16.6 狀態(tài)模式的優(yōu)缺點 16.7 狀態(tài)模式中的性能優(yōu)化點 16.8 狀態(tài)模式和策略模式的關(guān)系 16.9 JavaScript版本的狀態(tài)機 16.10 表驅(qū)動的有限狀態(tài)機 16.11 實際項目中的其他狀態(tài)機 16.12 小結(jié) 第17章 適配器模式 17.1 現(xiàn)實中的適配器 17.2 適配器模式的應(yīng)用 17.3 小結(jié) 第三部分 設(shè)計原則和編程技巧 第18章 單一職責(zé)原則 18.1 設(shè)計模式中的SRP原則 18.2 何時應(yīng)該分離職責(zé) 18.3 違反SRP原則 18.4 SRP 原則的優(yōu)缺點 第19章 最少知識原則 19.1 減少對象之間的聯(lián)系 19.2 設(shè)計模式中的LKP原則 19.3 封裝在LKP 原則中的體現(xiàn) 第20章 開放-封閉原則 20.1 擴展window.onload函數(shù) 20.2 開放和封閉 20.3 用對象的多態(tài)性消除條件分支 20.4 找出變化的地方 20.5 設(shè)計模式中的開放-封閉原則 20.6 開放-封閉原則的相對性 20.7 接受第一次愚弄 第21章 接口和面向接口編程 21.1 回到Java的抽象類 21.2 interface 21.3 JavaScript 語言是否需要抽象類和interface 21.4 用鴨子類型進行接口檢查 21.5 用TypeScript 編寫基于interface的命令模式 第22章 代碼重構(gòu) 22.1 提煉函數(shù) 22.2 合并重復(fù)的條件片段 22.3 把條件分支語句提煉成函數(shù) 22.4 合理使用循環(huán) 22.5 提前讓函數(shù)退出代替嵌套條件分支 22.6 傳遞對象參數(shù)代替過長的參數(shù)列表 22.7 盡量減少參數(shù)數(shù)量 22.8 少用三目運算符 22.9 合理使用鏈?zhǔn)秸{(diào)用 22.10 分解大型類 22.11 用return退出多重循環(huán) 參考文獻
你還可能感興趣
我要評論
|