工廠模式類似于現實生活中的工廠可以產生大量相似的商品,去做同樣的事情,實現同樣的效果;這時候需要使用工廠模式。
簡單的工廠模式可以理解為解決多個相似的問題;這也是她的優點;比如如下代碼:
~~~
function CreatePerson(name,age,sex) {
var obj = new Object();
obj.name = name;
obj.age = age;
obj.sex = sex;
obj.sayName = function(){
return this.name;
}
return obj;
}
var p1 = new CreatePerson("longen",'28','男');
var p2 = new CreatePerson("tugenhua",'27','女');
console.log(p1.name); // longen
console.log(p1.age); // 28
console.log(p1.sex); // 男
console.log(p1.sayName()); // longen
console.log(p2.name); // tugenhua
console.log(p2.age); // 27
console.log(p2.sex); // 女
console.log(p2.sayName()); // tugenhua
// 返回都是object 無法識別對象的類型 不知道他們是哪個對象的實列
console.log(typeof p1); // object
console.log(typeof p2); // object
console.log(p1 instanceof Object); // true
~~~
如上代碼:函數CreatePerson能接受三個參數name,age,sex等參數,可以無數次調用這個函數,每次返回都會包含三個屬性和一個方法的對象。
工廠模式是為了解決多個類似對象聲明的問題;也就是為了解決實列化對象產生重復的問題。
優點:能解決多個相似的問題。
缺點:不能知道對象識別的問題(對象的類型不知道)。
復雜的工廠模式定義是:將其成員對象的實列化推遲到子類中,子類可以重寫父類接口方法以便創建的時候指定自己的對象類型。
父類只對創建過程中的一般性問題進行處理,這些處理會被子類繼承,子類之間是相互獨立的,具體的業務邏輯會放在子類中進行編寫。
父類就變成了一個抽象類,但是父類可以執行子類中相同類似的方法,具體的業務邏輯需要放在子類中去實現;比如我現在開幾個自行車店,那么每個店都有幾種型號的自行車出售。我們現在來使用工廠模式來編寫這些代碼;
父類的構造函數如下:
~~~
// 定義自行車的構造函數
var BicycleShop = function(){};
BicycleShop.prototype = {
constructor: BicycleShop,
/*
* 買自行車這個方法
* @param {model} 自行車型號
*/
sellBicycle: function(model){
var bicycle = this.createBicycle(mode);
// 執行A業務邏輯
bicycle.A();
// 執行B業務邏輯
bicycle.B();
return bicycle;
},
createBicycle: function(model){
throw new Error("父類是抽象類不能直接調用,需要子類重寫該方法");
}
};
~~~
上面是定義一個自行車抽象類來編寫工廠模式的實列,定義了createBicycle這個方法,但是如果直接實例化父類,調用父類中的這個createBicycle方法,會拋出一個error,因為父類是一個抽象類,他不能被實列化,只能通過子類來實現這個方法,實現自己的業務邏輯,下面我們來定義子類,我們學會如何使用工廠模式重新編寫這個方法,首先我們需要繼承父類中的成員,然后編寫子類;如下代碼:
~~~
// 定義自行車的構造函數
var BicycleShop = function(name){
this.name = name;
this.method = function(){
return this.name;
}
};
BicycleShop.prototype = {
constructor: BicycleShop,
/*
* 買自行車這個方法
* @param {model} 自行車型號
*/
sellBicycle: function(model){
var bicycle = this.createBicycle(model);
// 執行A業務邏輯
bicycle.A();
// 執行B業務邏輯
bicycle.B();
return bicycle;
},
createBicycle: function(model){
throw new Error("父類是抽象類不能直接調用,需要子類重寫該方法");
}
};
// 實現原型繼承
function extend(Sub,Sup) {
//Sub表示子類,Sup表示超類
// 首先定義一個空函數
var F = function(){};
// 設置空函數的原型為超類的原型
F.prototype = Sup.prototype;
// 實例化空函數,并把超類原型引用傳遞給子類
Sub.prototype = new F();
// 重置子類原型的構造器為子類自身
Sub.prototype.constructor = Sub;
// 在子類中保存超類的原型,避免子類與超類耦合
Sub.sup = Sup.prototype;
if(Sup.prototype.constructor === Object.prototype.constructor) {
// 檢測超類原型的構造器是否為原型自身
Sup.prototype.constructor = Sup;
}
}
var BicycleChild = function(name){
this.name = name;
// 繼承構造函數父類中的屬性和方法
BicycleShop.call(this,name);
};
// 子類繼承父類原型方法
extend(BicycleChild,BicycleShop);
// BicycleChild 子類重寫父類的方法
BicycleChild.prototype.createBicycle = function(){
var A = function(){
console.log("執行A業務操作");
};
var B = function(){
console.log("執行B業務操作");
};
return {
A: A,
B: B
}
}
var childClass = new BicycleChild("龍恩");
console.log(childClass);
~~~
實例化子類,然后打印出該實例, 如下截圖所示:

console.log(childClass.name); // 龍恩
// 下面是實例化后 執行父類中的sellBicycle這個方法后會依次調用父類中的A
// 和B方法;A方法和B方法依次在子類中去編寫具體的業務邏輯。
childClass.sellBicycle("mode"); // 打印出 執行A業務操作和執行B業務操作
上面只是"龍恩"自行車這么一個型號的,如果需要生成其他型號的自行車的話,可以編寫其他子類,工廠模式最重要的優點是:可以實現一些相同的方法,這些相同的方法我們可以放在父類中編寫代碼,那么需要實現具體的業務邏輯,那么可以放在子類中重寫該父類的方法,去實現自己的業務邏輯;使用專業術語來講的話有2點:第一:弱化對象間的耦合,防止代碼的重復。在一個方法中進行類的實例化,可以消除重復性的代碼。第二:重復性的代碼可以放在父類去編寫,子類繼承于父類的所有成員屬性和方法,子類只專注于實現自己的業務邏輯。