在未讀《JavaScript設計模式》這本書前,在我的印象里,單例模式就是每個類只會產生一個實例,非常簡單。在細看到這個模式時候,有些疑惑單例模式與工廠模式的區別,雖然看起來像最大區別在於是否多次實例化。 單例(Singleton)模式 單例模式它限制了類的實例化次數只能一次。在實例不存在的情況下, ...
在未讀《JavaScript設計模式》這本書前,在我的印象里,單例模式就是每個類只會產生一個實例,非常簡單。在細看到這個模式時候,有些疑惑單例模式與工廠模式的區別,雖然看起來像最大區別在於是否多次實例化。
單例(Singleton)模式
單例模式它限制了類的實例化次數只能一次。在實例不存在的情況下,可以通過一個方法創建一個類來實現創建類的新實例;如果實例已經存在,它會簡單返回該對象的引用。(這跟我想的一樣)
例子:
var mySingleton = (function () { // Instance stores a reference to the Singleton var instance; function init() { // Singleton // Private methods and variables function privateMethod(){ console.log( "I am private" ); } var privateVariable = "Im also private"; var privateRandomNumber = Math.random(); return { // Public methods and variables publicMethod: function () { console.log( "The public can see me!" ); }, publicProperty: "I am also public", getRandomNumber: function() { return privateRandomNumber; } }; }; return { // Get the Singleton instance if one exists // or create one if it doesn't getInstance: function () { if ( !instance ) { instance = init(); } return instance; } }; })();
特別地方:
1. 單例不同於靜態類(或對象),因為我們可以推遲它們的初始化(通常是因為它們需要的參數信息在類定義時是無法獲得的),直到需要使用靜態實例時,無需使用資源或記憶體。
2. 單例的唯一實例能夠通過子類去擴展,使用者不用更改代碼就能使用一個擴展的實例。
3. 單例將導致測試變困難,不利於單元測試。
何時使用單例(When it really is a singleton):
一個類是否是一個單例,必須確定下麵三點:
1. Will every application use this class exactly the same way? (exactly is the key word)
2. Will every application ever need only one instance of this class? (ever and one are the key words)
3. Should the clients of this class be unaware of the application they are part of?
PS:這三點是由文章http://www.ibm.com/developerworks/webservices/library/co-single/index.html提出。
我的理解是:
1. 是否每個應用程式使用這個類的方式都完全相同?
2. 是否每個應用程式任何時候都只需要一個類的實例?
3. 使用者不需要知道該類是這應用程式的哪個部分?(或許翻譯不好)
當滿足這三個點,那就可以用單例。關鍵就在於類的使用方式都相同,並且不需要應用上下文。
工廠(Factory)模式
工廠模式提供一個通用的介面來創建對象。
例子:
function Car( options ) { this.doors = options.doors || 4; this.state = options.state || "brand new"; this.color = options.color || "silver"; } function Truck( options){ this.state = options.state || "used"; this.wheelSize = options.wheelSize || "large"; this.color = options.color || "blue"; } function VehicleFactory() {} VehicleFactory.prototype.createVehicle = function ( options ) { switch(options.vehicleType){ case "car": this.vehicleClass = Car; break; case "truck": this.vehicleClass = Truck; break; //defaults to VehicleFactory.prototype.vehicleClass (Car) } return new this.vehicleClass( options ); }; var carFactory = new VehicleFactory(); var car = carFactory.createVehicle( { vehicleType: "car", color: "yellow", doors: 6 } ); console.log( car instanceof Car ); // Outputs: true
何時使用工廠:
1. 當對象或組件設置非常複雜的時候。
2. 當需要根據所在的不同環境輕鬆生成對象的不同實例時。
3. 當處理很多共用相同屬性的小型對象或組件時。
4. 對象的實例只需要滿足一個約定——鴨子類型(duck typing)。利於解耦。
PS:鴨子類型——“當看到一隻鳥走起來像鴨子、游泳起來像鴨子、叫起來也像鴨子,那麼這隻鳥就可以被稱為鴨子。”我們並不關心對象是什麼類型,到底是不是鴨子,只關心行為。
抽象工廠(Abstract Factory)模式
書中描述:
使用抽象工廠模式場景:一個系統必須獨立於它所創建的對象的生成方式,或它需要與多種對象類型一起工作。
PS:我覺得沒描述清楚。
網上定義:
為創建一組相關或相互依賴的對象提供一個介面,而且無需指定他們的具體類。
PS:這個才比較清晰。
我的理解:
在工廠模式的加上一層抽象,工廠的工廠。
總結
單例模式和工廠模式概念上是比較簡單,但是在使用上需要留心。該不該用單例,就考慮上面講的單例三要點;該不該用工廠,就要看它是否帶來大量不必要的複雜性,帶來不必要的開銷(不為了用模式而用模式)。抽象工廠模式並沒有找到好的示例,就先略下。
另外越讀這本書,越覺得在某些譯文上有些問題,太過於直譯,我覺得應該要結合理解做翻譯,不然就像外國人講普通話,太怪了。
參考文獻
1. 《Learning JavaScript Design Patterns》 by Addy Osmani
https://addyosmani.com/resources/essentialjsdesignpatterns/book/
2. 《JavaScript設計模式》by 徐濤【譯】
本文為原創文章,轉載請保留原出處,方便溯源,如有錯誤地方,謝謝指正。
本文地址 :http://www.cnblogs.com/lovesong/p/5573521.html