JavaScript - 設計模式(簡單工廠和工廠模式)
2008年10月18日 23:28
經 常一個類或者一個對象都會包含其它的對象,當這些成員對象需要創建時,通常會使用 new 關鍵字和類的構造函數。問題是這樣會創建兩個類的依賴性。下面我們來看看一個模式,它能夠幫助這兩個類解耦,并使用一個方法來決定要創建哪個類的實例。我 們討論簡單工廠模式,它使用一個分離的類(經常是一個單態)來創建實例,還討論比較復雜的工廠模式,使用子類來決定使用哪個具體的類來實例化一個成員對 象。
// 簡單工廠 var BicycleShop = function() {}; BicycleShop.prototype = { sellBicycle: function(model) { var bicycle = BicycleFactory.createBicycle(model);; bicycle.assemble(); bicycle.wash(); return bicycle; } }; var BicycleFactory = { createBicycle: function(model) { var bicycle; switch(model) { case 'The Speedster': bicycle = new Speedster(); break; case 'The Lowrider': bicycle = new Lowrider(); break; case 'The Flatlander': bicycle = new Flatlander(); break; case 'The Comfort Cruiser': default: bicycle = new ComfortCruiser(); } Interface.ensureImplements(bicycle, Bicycle); // 確保實現接口 Bicycle return bicycle; } }; var Bicycle = new Interface('Bicycle', ['assemble', 'wash', 'ride', 'repair']); // 新建一個接口,Interface 類是模仿經典 OO 中的 Interface 的實現,以后有機會再介紹這個 Interface 的實現,如果要運行實例可以把有關Interface的代碼去掉 var Speedster = function() { // 實現接口 Bicycle // }; Speedster.prototype = { assemble: function() { // }, wash: function() { // }, ride: function() { // }, repair: function() { // } }; //工廠模式 var BicycleShop = function() {}; // 一個抽象類 BicycleShop.prototype = { sellBicycle: function(model) { var bicycle = this.createBicycle(model); bicycle.assemble(); bicycle.wash(); return bicycle; }, createBicycle: function(model) { throw new Error('Unsupported operation on an abstract class.'); } }; 以上是一個抽象類,不應該被實例化,應該通過繼承來實現自行車(bicycle)的生產,工廠模式就是把成員對象的實例化延遲到他的子類,以下是一個工廠模式子類的實現: var AcmeBicycleShop = function() {}; extend(AcmeBicycleShop, BicycleShop); // 繼承函數,這篇文章有介紹 AcmeBicycleShop.prototype.createBicycle = function(model) { var bicycle; switch(model) { case 'The Speedster': bicycle = new AcmeSpeedster(); break; case 'The Lowrider': bicycle = new AcmeLowrider(); break; case 'The Flatlander': bicycle = new AcmeFlatlander(); break; case 'The Comfort Cruiser': default: bicycle = new AcmeComfortCruiser(); } Interface.ensureImplements(bicycle, Bicycle); return bicycle; }; // 通過工廠模式來創建 XMLHTTPRequest 對象 /* AjaxHandler 接口 */ var AjaxHandler = new Interface('AjaxHandler', ['request', 'createXhrObject']); /* SimpleHandler 類. */ var SimpleHandler = function() {}; // 實現 AjaxHandler 接口 SimpleHandler.prototype = { request: function(method, url, callback, postVars) { var xhr = this.createXhrObject(); xhr.onreadystatechange = function() { if(xhr.readyState !== 4) return; (xhr.status === 200) ? callback.success(xhr.responseText, xhr.responseXML) : callback.failure(xhr.status); }; xhr.open(method, url, true); if(method !== 'POST') postVars = null; xhr.send(postVars); }, createXhrObject: function() { // Factory method. var methods = [ function() { return new XMLHttpRequest(); }, function() { return new ActiveXObject('Msxml2.XMLHTTP'); }, function() { return new ActiveXObject('Microsoft.XMLHTTP'); } ]; for(var i = 0, len = methods.length; i < len; i++) { try { methods[i](); } catch(e) { continue; } // If we reach this point, method[i] worked. this.createXhrObject = methods[i]; // Memoize the method. return methods[i]; } // If we reach this point, none of the methods worked. throw new Error('SimpleHandler: Could not create an XHR object.'); } }; 使用實例: var myHandler = new SimpleHandler(); var callback = { success: function(responseText) { alert('Success: ' + responseText); }, failure: function(statusCode) { alert('Failure: ' + statusCode); } }; myHandler.request('GET', 'script.php', callback); |