在说工厂方法模式之前先说一下安全模式类
什么是安全模式类,安全模式类就是说可以屏蔽使用这对类的错误使用造成的错误,这听起来有点不容易理解,那下面举一个例子。
现在我们创建了一个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条数据,并且增加了安全模式验证。
我们来分析一下代码,看看有哪些不同的地方。
最大的不同是我们把所有的子类改成了一个工厂类的原型方法中,这样做的好处可以减少代码的污染,得到了很好的封装,现在如果遇到了需求变更,我们只需要在这个工程类中增加或删除对应的方法即可。