前面把javascript的设计模式基本过了一遍,可以说是感慨很多,许多的思想都是从未接触过的,学起来难度也不小,但是我觉得这个过程是很值得的。如果以前是在足球场上踢野球的话,现在总算找到一个像模像样的教练在指导了,不一定会成为一个世界级的球星,但是水平至少也会比以前提高很多。
接下来会看看一些设计原则,设计原则是比模式更高一级的方法,是纲领性的内容。
单一职责(single responsable princple)被定为为“引起变化的原因”。如果一个方法承担了过多的职责,那么在需求发生变化的过程中,需要改写这个方法的可能性就越大。
因此SRP原则体现为:一个对象(方法)只做一件事情。
参考《javascript设计模式与开发实践》第18章
设计模式中的SRP原则
代理模式
下面这个例子是要在文档中创建一个img标签,并且要插入图片
在加载图片的时候,由于网速的限制需要预先加载一张本地图片,稍后会加载网络图片。 在这个过程中创建img标签
和更换图片源
是没有关系
的。所以最好是把这两个过程分为两个对象来处理。
//创建img标签的对象
var myImage = (function(){
var imgNode = document.createElement( 'img' );
document.body.appendChild( imgNode );
return {
setSrc: function( src ){
imgNode.src = src;
}
}
})();
//添加图片路径的对象
var proxyImage = (function(){
var img = new Image; //实例化标签对象
img.onload = function(){
myImage.setSrc( this.src ); //加载默认图片
}
return {
setSrc: function( src ){
myImage.setSrc( 'file:// /C:/Users/svenzeng/Desktop/loading.gif' );
img.src = src;
}
}
})();
//更改图片的路径,这个过程就和img标签的创建对象没有关系了。
proxyImage.setSrc( 'http:// );
迭代器模式
看下面段代码
//这段代码往文档中添加div元素,但是有限制,这里就只能添加数组
//有两个职责一个是添加元素,一个是遍历数据,所有有必要分开
var appendDiv=function(){
for(var i=0;l=data.length;i<l;i++){
var div=document.createElement('div');
div.innerHTML=data[i];
document.body.appendChild(div);
}
};
appenDiv([1,2,3,4,5,6])
使用单一职责原则改变代码
var each = function( obj, callback ) {//遍历的方法
//对象和数组都可以输入,灵活性加大,并且还可以修改
var value,
i = 0,
length = obj.length,
isArray = isArraylike( obj ); // isArraylike 函数未实现,可以翻阅jQuery 源代码
if ( isArray ) { // 迭代类数组
for ( ; i < length; i++ ) {
callback.call( obj[ i ], i, obj[ i ] );
}
} else {
for ( i in obj ) { // 迭代object 对象
value = callback.call( obj[ i ], i, obj[ i ] );
}
}
return obj;
};
//根据输入数据的元素添加方法
var appendDiv = function( data ){
each( data, function( i, n ){ //使用each方法来执行遍历
//在回调函数中根据遍历数据添加元素至文档中
var div = document.createElement( 'div' );
div.innerHTML = n;
document.body.appendChild( div );
});
};
appendDiv( [ 1, 2, 3, 4, 5, 6 ] );//数组数据
appendDiv({a:1,b:2,c:3,d:4} ); //对象数据
单例模式
在前面已经有笔记了。实际是把实际操作和创建单例的方法分别封装在两个方法里。
var createLoginLayer = (function(){//创建元素的方法
var div;
return function(){
if ( !div ){
div = document.createElement( 'div' );
div.innerHTML = '我是登录浮窗';
div.style.display = 'none';
document.body.appendChild( div );
}
return div; //单例的判断依据
}
})();
//创建和检测单例的方法,参数为创建元素的方法
var getSingle = function( fn ){ // 获取单例
var result;
return function(){
return result || ( result = fn .apply(this, arguments ) );
//这个地方要注意apply和arguments的应用
}
};
var createLoginLayer = function(){ // 创建登录浮窗
var div = document.createElement( 'div' );
div.innerHTML = '我是登录浮窗';
document.body.appendChild( div );
return div;
};
var createSingleLoginLayer = getSingle( createLoginLayer );
var loginLayer1 = createSingleLoginLayer();
var loginLayer2 = createSingleLoginLayer();
alert ( loginLayer1 === loginLayer2 ); // 输出: true //为同一对象
```
装饰者模式
前面的设计模式里也有介绍
装饰者模式可以动态为对象添加方法或指责。从而也使的对象的功能单一化。
下面两个函数调用的时候指向同一个对象。
Function.prototype.after = function( afterfn ){
var __self = this;
return function(){
var ret = __self.apply( this, arguments );
//执行原函数
afterfn.apply( this, arguments );//执行after函数
return ret;
}
};
var showLogin = function(){
console.log( '打开登录浮层' );
};
var log = function(){
console.log( '上报标签为: ' + this.getAttribute( 'tag' ) );
};
document.getElementById( 'button' ).onclick = showLogin.after( log );
// 打开登录浮层之后上报数据
#####单一职责原则减低了单个类或者对象的复杂度,按照指责把对象分解成更小的粒度。有助于代码的复用,修改和测试。但是代码复杂度是提高了。怎么平衡呢?这是个问题。