JavaScript设计模式(二):工厂模式
1. 简单工厂
工厂模式主要用来创建同一类对象,解决相似问题。它将成员对象的实例化操作(new
操作)封装在一个外部函数中,我们需要什么对象,就要调用工厂方法来创建对应对象。其内部通常使用 if-else
或 switch-case
条件语句来分别创建不同类型对象。
function Man(){}
Man.prototype = {...}
function Woman(){}
Woman.prototype = {...}
function PersonFactory(s){
if(s == 'man'){
return new Man();
}else if(s == 'woman'){
return new Woman();
}else{
return null;
}
}
PersonFactory('man');
// 异步对象工厂
function CreateXHR(){
var xhr = null;
if(window.XMLHttpRequest){
xhr = new XMLHttpRequest();
}else if(window.ActiveXObject){
xhr = new ActiveXObject('Msxml2.XMLHTTP');
}
return xhr;
}
缺陷:违反了开闭原则
什么是开闭原则?
软件中的对象(类、模块、函数等)应该对于扩展开放,而对于修改是封闭的。
也就是说,当需要改变一个程序的功能或者给程序增加新功能时,可以增加代码但不允许改变程序的源代码。因为修改源代码常常是危险的,尤其是在代码十分复杂的情况下,我们永远不知道改动源码会出现什么副作用。
// 当我们想增加child类时 不得不改变PersonFactory函数
function PersonFactory(s, name){
if(s == 'man'){
return new Man(name);
}else if(s == 'woman'){
return new Woman(name);
}else if(s == 'child'){
return new Child(name);
}else{
return null;
}
}
PersonFactory('man', 'Tim');
2. 工厂方法
工厂方法使一个类的实例化延迟到其子类。也就是遵从开闭原则,引进新类时不改变原有的东西,仅需要添加新的具体工厂类即可。
如以下代码,我们想添加其它 Person
类,只需要写在 PersonFactory
的原型中就可以,而不必改变PersonFactory
。
var PersonFactory = function(s, name){
return new this[s](name);
}
PersonFactory.prototype = {
man: function(name){
this.name = name;
},
women: function(name){
this.name = name;
},
child: function(name){
this.name = name;
}
}
new PersonFactory('child', 'Bob');
3. 总结
- 简单工厂适用于创建单一对象,而工厂方法则适合创建多类对象。
- 简单工厂将对象实例化的选择判断放在工厂内部,而工厂方法将简单工厂的内部逻辑判断移到了外部,本来修改工厂类,现在修改原型即可。