我们来看一个例子,使用Cache('local').set('username', 'wen')设置一个localStorage键为username,值为wen的本地缓存。
先来分析Cache('local').set('username', 'wen')这段代码,Cache('local')返回一个对象,然后调用对象的set方法。
我第一反应是采用一个闭包来生成对象,示例代码如下:
var Cache = (function(){
var local = {
set: function(key, value) {
console.log('local: ' + key + ' => ' + value);
}
},
session = {
set: function(key, value) {
console.log('session: ' + key + ' => ' + value);
}
};
return function(type) {
type = type || 'local';
switch (type){
case 'local' :
return local;
case 'session' :
return session;
default:
return void 0;
}
};
}());
Cache('local').set('username', 'wen'); //local:
Cache().set('username', 'wen'); //local: username => wen
Cache('session').set('username', 'wen'); //session: username => wen
在这个例子中,每次增加一个对象,还必须修改Cache对象返回的对象代码,代码的耦合性较高,我们可以采用工厂方法来对这些代码进行解耦。工厂方法的目的就是为了创建对象。
工厂方法通常在类的静态方法中实现,主要用于创建相似对象时执行重复操作以及为客户端提供创建对象的接口。
下面,我们采用JavaScript实现工厂方法:
- 公共父构造函数CacheMaker;
- 实现CacheMaker的静态方法factory(),用于创建Cache对象;
- 实现CacheMaker.Local, CacheMaker.Session,这些构造函数定义为CacheMaker的静态方法,以便全局命名空间免受污染。
代码如下:
function CacheMaker() {}
CacheMaker.prototype.init = function() {
console.log('CacheMaker init');
}
CacheMaker.factory = function(type) {
var constr = type || 'Local';
//判断构造函数是否存在
if (typeof CacheMaker[constr] !== 'function') {
return void 0;
}
//使原型继承父类,但仅继承一次
if (typeof CacheMaker[constr].prototype.init !== 'function') {
CacheMaker[constr].prototype = new CacheMaker();
}
//创建实例
return new CacheMaker[constr]();
}
//Local构造方法
CacheMaker.Local = function() {
this.set = function(key, value) {
console.log('local: ' + key + ' => ' + value);
};
}
//Session构造方法
CacheMaker.Session = function() {
this.set = function(key, value) {
console.log('session: ' + key + ' => ' + value);
}
}
var local = CacheMaker.factory('Local'),
session = CacheMaker.factory('Session');
local.set('username', 'wen'); // local: username => wen
session.set('username', 'wen'); // session: username => wen
当需要其他类型的Cache时,只需要增加CacheMaker相对应的静态方法即可。重构后的代码扩展性更好,维护成本也降低了。