經(jīng) 常一個(gè)類或者一個(gè)對(duì)象都會(huì)包含其它的對(duì)象,當(dāng)這些成員對(duì)象需要?jiǎng)?chuàng)建時(shí),通常會(huì)使用 new 關(guān)鍵字和類的構(gòu)造函數(shù)。問(wèn)題是這樣會(huì)創(chuàng)建兩個(gè)類的依賴性。下面我們來(lái)看看一個(gè)模式,它能夠幫助這兩個(gè)類解耦,并使用一個(gè)方法來(lái)決定要?jiǎng)?chuàng)建哪個(gè)類的實(shí)例。我 們討論簡(jiǎn)單工廠模式,它使用一個(gè)分離的類(經(jīng)常是一個(gè)單態(tài))來(lái)創(chuàng)建實(shí)例,還討論比較復(fù)雜的工廠模式,使用子類來(lái)決定使用哪個(gè)具體的類來(lái)實(shí)例化一個(gè)成員對(duì) 象。
// 簡(jiǎn)單工廠
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); // 確保實(shí)現(xiàn)接口 Bicycle
return bicycle;
}
};
var Bicycle = new Interface('Bicycle', ['assemble', 'wash', 'ride', 'repair']); // 新建一個(gè)接口,Interface 類是模仿經(jīng)典 OO 中的 Interface 的實(shí)現(xiàn),以后有機(jī)會(huì)再介紹這個(gè) Interface 的實(shí)現(xiàn),如果要運(yùn)行實(shí)例可以把有關(guān)Interface的代碼去掉
var Speedster = function() { // 實(shí)現(xiàn)接口 Bicycle
//
};
Speedster.prototype = {
assemble: function() {
//
},
wash: function() {
//
},
ride: function() {
//
},
repair: function() {
//
}
};
//工廠模式
var BicycleShop = function() {}; // 一個(gè)抽象類
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.');
}
};
以上是一個(gè)抽象類,不應(yīng)該被實(shí)例化,應(yīng)該通過(guò)繼承來(lái)實(shí)現(xiàn)自行車(bicycle)的生產(chǎn),工廠模式就是把成員對(duì)象的實(shí)例化延遲到他的子類,以下是一個(gè)工廠模式子類的實(shí)現(xiàn):
var AcmeBicycleShop = function() {};
extend(AcmeBicycleShop, BicycleShop); // 繼承函數(shù),
這篇文章有介紹
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;
};
// 通過(guò)工廠模式來(lái)創(chuàng)建 XMLHTTPRequest 對(duì)象
/* AjaxHandler 接口 */
var AjaxHandler = new Interface('AjaxHandler', ['request', 'createXhrObject']);
/* SimpleHandler 類. */
var SimpleHandler = function() {}; // 實(shí)現(xiàn) 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.');
}
};
使用實(shí)例:
var myHandler = new SimpleHandler();
var callback = {
success: function(responseText) { alert('Success: ' + responseText); },
failure: function(statusCode) { alert('Failure: ' + statusCode); }
};
myHandler.request('GET', 'script.php', callback);