在說工廠方法模式之前先說一下安全模式類
什麼是安全模式類,安全模式類就是說可以屏蔽使用這對類的錯誤使用造成的錯誤,這聽起來有點不容易理解,那下面舉一個例子。
現在我們創建了一個Dome類如下:
var Dome = function(text){
this.text = text;
}
Dome.prototype = {
show:function(){
console.log(this.text);
}
}
如果我們要使用這個Dome類必須要使用new關鍵字來執行(var d = new Dome()),但是有時往往會忽略掉new關鍵字(var d = Dome()),此時當我們調用Dome類的show()方法時會出現如下錯誤。
//Uncaught TypeError:Connot read property 'show' of undefined
我們有一種簡單的解決方案:在構造函數開始時先判斷當前的this指代是不是類(Dome),如果是則通過new關鍵字創建對象,如果不是說明類在全局域中執行,即只想window。代碼如下:
var Dome = function(content){
if(!(this instanceof Dome)){
return new Dome(content);
}
}
Dome.prototype = {
show:function(){
console.log("獲取成功");
}
}
var d1 = Dome();
d1.show(); //獲取成功
//或者
var d2 = new Dome();
d2.show(); //獲取成功
工廠方法模式
工廠方法模式是將實際創建的對象工作推遲到子類當中,這樣核心類就成了抽象類。
舉個例子:現在需要做一些課程培訓的廣告,包括JS、HTML、CSS三個部分,他們分別採用不同的背景顏色。如果按照原來的簡單工廠模式的思想,我們首先需要創建對應的3個類,如下:
//創建JS類
var JS = function (content) {
this.content = content;
(function (content) {
var div = document.createElement('div');
div.innerHTML = content;
div.style.border = '1px solid red';
document.getElementById("container").appendChild(div);
})(content);
};
//創建JS類
var HTML = function (content) {
this.content = content;
(function (content) {
var div = document.createElement('div');
div.innerHTML = content;
div.style.border = '1px solid yellow';
document.getElementById("container").appendChild(div);
})(content);
};
//創建JS類
var CSS = function (content) {
this.content = content;
(function (content) {
var div = document.createElement('div');
div.innerHTML = content;
div.style.border = '1px solid green';
document.getElementById("container").appendChild(div);
})(content);
};
function JobFactory(type, content) {
switch (type) {
case 'JS':
return new Js(content);
case 'HTML':
return new HTML(content);
case 'CSS':
return new CSS(content);
}
}
我們可以看到這樣寫出來的代碼量很大,並且當每次要增加需求的時候我們都至少要修改兩個地方,這顯然降低了效率。
那麼接下來我們看一下工廠方法模式的優勢所在,直接上代碼:
var Factory = function (type, content) {
if (this instanceof Factory) {
var s = new this[type](content);
return s;
} else {
return new Factory(type, content);
}
this.content = content;
};
Factory.prototype = {
JS: function (content) {
// this.content = content;
(function (content) {
var div = document.createElement('div');
div.innerHTML = content;
div.style.border = '1px solid green';
document.getElementById("container").appendChild(div);
})(content);
},
CSS: function (content) {
this.content = content;
(function (content) {
var div = document.createElement('div');
div.innerHTML = content;
div.style.border = '1px solid red';
document.getElementById("container").appendChild(div);
})(content);
},
HTML: function (content) {
this.content = content;
(function (content) {
var div = document.createElement('div');
div.innerHTML = content;
div.style.border = '1px solid yellow';
document.getElementById("container").appendChild(div);
})(content);
}
}
var data = [
{
type: 'HTML',
content: "HTML"
}, {
type: 'CSS',
content: "CSS模塊"
}, {
type: 'JS',
content: "JS模塊"
}, {
type: 'JS',
content: "JS模塊"
}, {
type: 'CSS',
content: "CSS模塊"
}
];
for (var i = 0; i < data.length; i++) {
Factory(data[i].type, data[i].content);
}
直觀的看上去貌似代碼量比原來的還要多,那是因爲我們這裏顯示了5條數據,並且增加了安全模式驗證。
我們來分析一下代碼,看看有哪些不同的地方。
最大的不同是我們把所有的子類改成了一個工廠類的原型方法中,這樣做的好處可以減少代碼的污染,得到了很好的封裝,現在如果遇到了需求變更,我們只需要在這個工程類中增加或刪除對應的方法即可。