1. 程式人生 > >《JavaScript設計模式與開發實踐》知識點筆記

《JavaScript設計模式與開發實踐》知識點筆記

使用 接收 context 產生 換算 應該 語言 pan 統一

1、javaScript沒有提供傳統面向對象語言中的類式繼承,而是通過原型委托的方式來實現對象與對象之間的繼承。

2、靜態類型語言在編譯時便已確定變量的類型,而動態類型語言的變量類型要到程序運行的時候,待變量被賦予某個值後,才會具有某種類型。

3、JavaScript是一門典型的動態類型語言

4、利用鴨子類型的思想,我能在動態類型語言中實現一個原則:“面向接口編程,而不是面向實現編程”

5、多態:同一操作作用於不同的對象上面,可以產生不同的解釋和不同的執行結果。

6、多態背後的思想是將“做什麽”和“誰去做以及怎樣去做”分離開來,也就是將“不變的事物”與“可能改變的事物”分離開來。

7、多態的最根本的好處在於,你不必再向對象詢問“你是什麽類型”而後根據得到的答案調用對象的某個行為——你只管調用該行為就是了,其他的一切多態機制都會為你安排妥當。

8、從設計模式的角度出發, 封裝在更重要的層面體現為封裝變化

9、創建型模式,結構型模式,行為型模式

10、JavaScript選擇基於原型的面向對象系統

11、原型模式不關心對象的具體類型,而是找到一個對象,然後通過克隆來創建一個一模一樣的對象

12、原型模式的實現關鍵,是語言本身是否提供了clone方法,ECMAScript5提供了Object.create方法,可以用來克隆對象

13、所有的JavaScript對象都是從某個對象上克隆而來的

14、原型編程中的一個重要特性:當對象無法響應某個請求時,會把該請求委托給自己的原型

15、原型編程泛型至少包括以下基本規則:

1.所有的數據都是對象

2.要得到一個對象,不是通過實例化類,而是找到一個對象做為原型並克隆它

3.對象會記住它的原型

4.如果對象無法響應某個請求,它會把這個請求委托給它自己的原型

16、JavaScript中的根對象是Object.prototype對象,該對象是一個空對象

17、用new運算符來創建對象的過程,實際上也只是先克隆Object.prototype對象,再進行一些其他額外操作的過程

18、對於“對象把請求委托給它自己的原型”這句話,更好的說法是對象把請求委托給它的構造器的原型

19、__proto__就是對象跟“對象構造器的原型”聯系起來的紐帶,__proto__指向構造器的prototype

20、原型鏈終點,Object.prototype,也就是null

21、設計模式在很多時候其實都體現了語言的不足之處,如果要使用設計模式,不如去找一門更好的語言。

22、this具體指向哪個對象是在運行時基於函數的執行環境動態綁定的,而非函數被聲明時的環境

23、借用構造方法

24、使用Array.prototype.push方法需要滿足兩個條件:

1.對象本身要可以存取屬性

2.對象的length屬性可讀寫

25、命令模式的意圖是把請求封裝為對象,從而分離請求的發起者和請求的接收者(執行者)之間的耦合關系。在命令被執行之前,可以預先往命令對象中植入命令的接收者。

26、高階函數是指至少滿足下列條件之一的函數:

1.函數可以作為參數被傳遞

2.函數可以作為返回值輸出

27、回調函數的應用不僅只在異步請求中,當一個函數不適合執行一些請求時,我們也可以把這些請求封裝成一個函數,並把它作為參數傳遞給另外一個函數,“委托”給另一個函數來執行。

28、AOP(面向切面編程)的主要作用是把一些跟核心業務邏輯模塊無關的功能抽離出來,這些跟業務邏輯無關的功能通常包括日誌統計,安全控制,異常處理等。

29、JavaScript實現AOP,都是指把一個函數“動態織入”到另一個函數中。

30、裝飾者模式精華思想:裝飾者對象和它所裝飾的對象擁有一致的接口,所以它們對使用該對象的客戶來說是透 明的,被裝飾的對象也並不需要了解它曾經被裝飾過,這種透明性使得我們可以遞歸地嵌套任意 多個裝飾者對象 ,有點類似遞歸的思想

31、要實現一個標準的單例模式並不復雜,無非是用一個變量來標誌當前是否已經為某個類創建過對象,如果是,則在下一次獲取該類的實例時,直接返回之前創建的對象。

32、將不變的部分和變化的部分隔開是每個設計模式的主題

33、策略模式的目的就是將算法的使用與算法的實現分離開來。

34、一個基於策略模式的程序至少由兩部分組成。第一個部分是一組策略類,策略類封裝了具體的算法,並負責具體的計算過程。第二部分是環境類Context,Context接受客戶的請求,隨後把請求委托給一個策略類。要做到這點,說明Context中要維持對某個策略對象的引用。

35、策略模式的思想:定義一系列的算法,把它們一個個封裝起來,並且使它們可以相互替換。其實也就是把多條if封裝成多條路徑,傳入不同的參數,執行不同的路徑,每條路徑策略不同,但是大體目的都是一致的。

36、策略模式的實現並不復雜,關鍵是如何從策略模式的實現背後,找到封裝變化、委托和多態性這些思想的價值

37、從定義上看,策略模式就是用來封裝算法的。但如果把策略模式僅僅用來封裝算法,未免有點大材小用。在實際開發中,我們通常會把算法的含義擴散開來,是策略模式也可以用來封裝一系列的“業務規則”。只要這些業務規則指向的目標一致,並且可以被替換使用,我們就可以使用策略模式來封裝它們。

37、代理模式是為一個對象提供一個代用品或占位符,以便控制對它的訪問。

38、代理模式的關鍵是,當客戶不方便直接訪問一個對象或者不滿足需要的時候,提供一個替身對象來控制對這個對象的訪問,客戶實際上訪問的是替身對象,替身對象請對請求做出一些處理之後,再把請求轉交給本體對象。

39、虛擬代理把一些開銷很大的對象,延遲到真正需要它的時候才去創建,虛擬代理關鍵思路就是滿足一定的條件了才真正執行原對象的方法。

40、代理就是在代理對象的一個方法中等到合適的時間(比如說圖片預加載完),去執行目標對象的方法,這兩個方法是同名的,所以對於用戶來說這個過程是透明的。代理負責預加載圖片,預加載操作完成之後,把請求重新交給本體MyImage。

41、給img節點設置src和圖片預加載這兩個功能,被隔離在兩個對象裏,他們可以各自變化而不影響對方。何況就算有一天我們不再需要預加載,那麽只需要改成請求本體而不是請求代理對象即可。

42、緩存代理可以為一些開銷大的運算結果提供暫時的存儲,在下次運算時,如果傳遞進來的參數跟之前的一致,則可以直接返回前面存儲的運算結果。

43、比如說分頁請求,我們就可以使用緩存代理來緩存我們已經請求的數據,而不是每次都從後臺抓取。

44、代理模式包括許多小分類,在JavaScript開發中最常用的是虛擬代理和緩存代理。雖然代理模式非常有用,但我們在編寫業務代碼的時候,往往不需要去預先猜測是否需要使用代理模式,當真正發現不方便直接訪問某個對象的時候,在編寫代理也不遲。因為真正的對象邏輯不會因為代理而改變,代理的目的只是在合適的時間點去執行原對象。

45、

發布-訂閱者模式可以取代對象之間硬編碼的通知機制,一個對象不用再顯式地調用另外一個對象的某個接口。發布-訂閱模式讓兩個對象松耦合地聯系在一起,雖然不太清楚彼此的細節,但這不影響他們之間的通信

46、

實現發布-訂閱者思路:

1.首先要指定好誰充當發布者(比如售樓處)

2.然後給發布者添加一個緩存列表,用於存放回調函數以便通知訂閱者(售樓處的花名冊)

3.最後發布消息的時候,發布者會遍歷這個緩存列表,一次觸發裏面存放的訂閱者回調函數(遍歷花名冊,挨個發短信)

47、

發布-訂閱模式的優點非常明顯,一位時間上的解耦,二為對象之間的解耦。發布-訂閱者模式還可以用來幫助實現一些別的設計模式,例如中介者模式。

48、

命令模式應用場景:

有時候需要向某些對象發送請求,但是並不知道請求的接受者是誰,也不知道被請求的操作是什麽,此時希望用一種松耦合的方式來設計軟件,使得請求發送者和請求接收者能夠消除彼此之間的耦合關系。

49、

設計模式的主題總是把不變的事物和變化的事物分離開來,命令模式也不例外。按下按鈕之後會發生一些事情是不變的,而具體會發生什麽事情是可變的。

50、

命令模式的由來,其實是回調函數的一個面向對象的替代品,回調是直接一個函數,比如說添加。而命令模式是一個對象,裏面可以有多種方法,比如說添加和撤銷,所以我們要擁有添加和撤銷的功能,最好還是封裝成command對象來傳遞,而不是直接傳遞函數。

51、

命令模式在js中說白了就是,我要執行一個方法,但是我不知道它的名字和具體代碼,那麽我就執行命令對象通過閉包返回的execute方法返,這個方法返回的就是我們想要的函數。具體例子看129頁

52、

撤銷是命令模式裏一個非常有用的功能,試想一下開發一個圍棋程序的時候,我們把每一步棋子的變化都封裝成命令,則可以輕易地實現悔棋功能。同樣,撤銷命令還可以用於實現文本編輯器Ctrl+z功能。

53、

組合模式就是用小的子對象來構建更大的對象,而這些小的子對象本身也許是由更小的“孫對象”構成的

54、

當我們往萬能遙控器裏面添加一個命令的時候,並不關心這個命令是宏命令還是普通子命令。這點對於我們不重要,我們只需要確定它是一個命令,並且這個命令擁有可執行的execute方法,那麽這個命令就可以被添加進萬能遙控器。

55、

組合模式命令就在於每層對象都有execute方法,根對象執行execute,就會遍歷所有子孫對象,體現出了多態。

56、

每當對最上層的對象進行一次請求時,實際上是在對整個樹進行深度優先的搜索

57、

組合模式最大的有點就是在於可以一致的對待組合對象和基本對象

58、

客戶希望統一對待樹中的所有對象,組合模式使客戶可以忽略組合對象和葉對象的區別,客戶在面對這棵樹的時候,不用關心當前正在處理的對象是組合對象還是葉對象,也就是不用寫一堆if、else語句來分別處理他們,組合對象和葉對象會各自做自己正確的事情,這是組合模式的重要能力。

59、

組合模式缺點:系統中的每個對象看起來都與其他對象差不多,他們的區別只有在運行的時候才會凸顯出來,這會使代碼難以理解。此外,如果通過組合模式創建了太多的對象,那麽這些對象可能會讓系統擔負不起。

60、

基於繼承的設計模式——模板方法模式

61、

模板方法模式由兩部分結構組成,第一部分是抽象父類,第二部分是具體的實現子類。通常在抽象父類中封裝了子類的算法框架,包括實現一些公共方法以及封裝子類中所有方法的執行順序,子類通過繼承這個抽象類,也繼承了整個算法結構,並且可以選擇重寫父類的方法。

62、

p154,Beverage.prototype.init被稱為模板方法的原因是,該方法中封裝了子類的算法框架,它作為一個算法的模板,指導子類以何種順序去執行哪些方法。

63、

JavaScript不支持抽象類,我們以下面兩種變通的方法來處理:

1、用鴨子類型來模擬接口檢查,以確保子類中確實重寫了父類的方法。

2、讓Beverage.prototype.brew等方法拋出異常,如果因為粗心忘記編寫Coffee.prototype.brew方法,那麽至少我們會在程序運行時得到一個錯誤。

64、

放置鉤子是隔離變化的一種常見手段。我們在父類中容易變化的地方放置鉤子,鉤子可以有一個默認的實現,究竟要不要“掛鉤”,這由子類自行決定。鉤子方法返回結果決定了模板方法後面部分的執行步驟,也就是程序接下來的走向,這樣一來,程序就擁有了變化的可能。

65、

用模板方法模式編寫一個程序時,就意味著子類放棄了對自己的控制權,而是改為父類通知子類,哪些方法應該在什麽時候被調用。做為子類,只負責提供一些設計上的細節。

66、

在JavaScript中,我們很多時候都不需要依樣畫瓢地去實現一個模板方法模式,高階函數是更好的選擇。

67、

享元模式的核心是運用共享技術來有效支持大量細粒度的對象。

68、

享元模式要求將對象的屬性劃分為內部狀態與外部狀態(狀態在這裏通常指屬性)。享元模式的目標是盡量減少共享對象的數量,關於如何劃分內部狀態和外部狀態,下面的幾條經驗提供了一些指引。

1、內部狀態存儲於對象內部。

2、內部狀態可以被一些對象共享

3、內部狀態獨立於具體的場景,通常不會改變

4、外部狀態取決於具體的場景,並根據場景而變化,外部狀態不能被共享

69、

剝離了外部狀態的對象稱為共享對象,外部狀態在必要時被傳入共享對象來組裝成一個完整的對象。

70、

享元模式是一種用時間換空間的優化模式

71、

享元模式的關鍵是如何區別內部狀態和外部狀態

72、

享元模式適用場景:

1、一個程序中使用了大量的相似對象

2、由於使用了大量對象,造成很大的內存開銷

3、對象的大多數狀態都可以變為外部狀態

4、剝離出對象的外部狀態之後,可以用相對較少的共享對象取代大量對象

73、

當對象沒有內部狀態的時候,生產共享對象的工廠實際上變成了一個單例工廠。

74、

對象池跟祥元模式有一些相似之處,但沒有分離內部狀態和外部狀態這個過程。

75、

享元模式是為解決性能問題而生的模式,這跟大部分模式的誕生原因都不一樣

76、

職責鏈模式的定義是:使多個對象都有機會處理請求,從而避免請求的發送者和接收者之間的耦合關系,將這些對象連成一條鏈,並沿著這條鏈傳遞該請求,直到有一個對象處理它為止

77、

職責鏈模式最大優點:請求發送者只需要知道鏈中的第一個節點,從而弱化了發送者和一組接收者之間的強聯系。

78、

用AOP來試下職責鏈既簡單又巧妙,但這種把函數疊在一起的方式,同時也疊加了函數的作用域,如果鏈條太長的話,也會對性能有較大的影響。

79、

中介者模式的作用就是解除對象與對象之間的緊耦合關系

80、

如果對象之間的復雜耦合確實導致調用和維護出現了困難,而且這些耦合度隨項目的變化呈指數增長曲線,那我們就可以考慮用中介者模式來重構代碼

81、

狀態模式的關鍵是區分事物內部狀態,事物內部狀態的改變往往會帶來事物的行為改變。

82、

狀態模式的好處很明顯,它可以使每一種狀態和它對應的行為之間的關系局部化,這些行為被分散和封裝在各自對應的狀態類中,便於閱讀和管理代碼

83、

狀態模式定義:

允許一個對象在其內部狀態改變時改變他的行為,對象看起來似乎修改了它的類

84、

策略模式和狀態模式的相同點是,它們都有一個上下文,一些策略或者狀態類,上下文把請求委托給這些類來執行

85、

策略模式和狀態模式的不同點是,策略模式中的各個策略類之間是平等又平行的,它們之間沒有任何聯系, 所以客戶必須熟知這些策略類的作用,以便客戶可以隨時主動切換算法;而在狀態模式中,狀態 和狀態對應的行為是早已被封裝好的,狀態之間的切換也早被規定完成,改變行為這件事情 發生在狀態模式內部。對客戶來說,並不需要了解這些細節。這正是狀態模式的作用所在。

86

適配器模式的作用是解決兩個軟件實體間的接口不兼容的問題,使用適配器模式之後,原本由於接口不兼容而不能工作的兩個軟件實體可以一起工作

87、

如果現有的接口已經能夠正常工作,那我們就永遠不會用上適配器模式,適配器模式是一種“亡羊補牢”的模式,沒有人會在程序設計之初就使用它

88、

常見的設計原則:單一職責原則,裏氏替換原則,依賴倒置原則,接口隔離原則,合成復用原則,最少知識原則

89、

開放-封閉原則:軟件實體等應該是可以拓展的,但是不可修改

90、

用對象的多態性消除條件分支

放置掛鉤也是分離變化的一種方式

91、

在js中,策略模式和命令模式等都可以用回調函數輕松實現

92、

發布——訂閱者模式用來降低多個對象之間的依賴關系,他可以取代對象之間硬編碼的通知機制,一個對象不用再顯式地調用另外一個對象的接口。

《JavaScript設計模式與開發實踐》知識點筆記