设计原则之单一职责原则 javascript

就一个类而言,应该仅有一个引起它变化的原因。这就是所谓的单一职责原则(SRP),这里的职责指的是引起变化的动机,如果有两个动机去改写一个类,那么就违反了单一职责原则,其实总体来说SRP要求的就是高内聚低耦合,但往往在实际的敲代码过程中很容易造成职责分散,也就是某一个职责往往在不经意间就被我们分成了多个职责。

如果一个类有两个职责,那么当你修改其中一个的时候,很容易引起另一个的变化,导致整个类进而整个程序无法运行,所以我们提倡单一职责原则来编写易于维护的代码。因为是在javascript中,我们主要讨论对象和方法的单一职责原则的实现,即一个对象或者方法只做一件事。

SRP在很多的设计模式中都有体现,比如代理模式、迭代器模式、单例模式、装饰者模式。


下面是代理模式的例子,代理模式实现图片预加载,myImage负责添加img标签,而代理proxyImage负责预加载图片,并在预加载后将请求交给本体

var myImage = (function(){
	var imgNode = document.createElement( "img" );
	document.body.appendChild( imgNode );

	return function( src ){
		imgNode.src = src;
	};
})();

var proxyImage = (function(){
	var img = new Image;

	img.onload = function(){
		myImage( this.src );
	};

	return function( src ){
		myImage( 'onloading.gif' );
		img.src = src;
	};
})();

proxyImage( 'https://xxxxx' );

myImage 首先创建了一个img标签并将其添加到body上,然后返回一个函数,函数功能为设置myImage内闭包的imgNode的地址。

proxyImage 首先new了一个Image对象,然后对其设置一个onload事件,功能为调用myImage函数实现当图片加载完后设置图片地址, 最后返回了一个函数,功能是先设置loading图片在给闭包内的img对象设置src属性,以便onload事件触发后读取地址。

代理负责预加载,而且并不关心本体如何工作,他的职责只有预加载,而本体则只负责添加并设置img地址,同时留给客户的接口也只有一个输入图片地址的函数,代理完全隐藏起来,而且职责分明,都只有一个被修改的动机。


下面是迭代器模式的例子,其提供了一种顺序访问一个聚合对象中各个元素,而又不需要暴露该对象内部表示的方法,该方法就只有一个职责,即迭代聚合对象

var each = function( obj, callback ){
    var value,
        i = 0,
        length = obj.length,
        isArray = isArraylike( obj );//此处就不具体实现了,有兴趣的朋友可以自行查阅

    if( isArray ){//迭代类数组
        for( ; i < length; i++ ){
            callback.call( obj[ i ], i, obj[ i ] );
        }
    }else{//迭代object对象
        for( i in obj ){
            value = callback.call( obj[ i ], i, obj[ i ] );
        }
    }

    return obj;
};

var appendDiv = function( data ){
    each( data, function( i, n ){
        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 } );
each 即迭代器函数,这里面只有两种迭代方式,即数组和对象迭代, 首先判断应该迭代的方式,数组则进行for循环callback迭代,对象则进行for in循环迭代

appendDiv 使用each函数传递对象和方法进去


至于装饰者模式,装饰者模式是给对象动态增加职责的方法,所以其实这也是分离职责的一种方式,装饰者模式是一种很强大的模式,有兴趣的朋友可以自行查阅一下,后期我也会出一篇博客讲讲他。


整个SRP的难点是何时如何分离职责,首先要明确的是不是所有的职责都应该分离,实际的编写代码过程中其实也会遇到因为一些原因而违反SRP原则的时候,比如说jquery方法中的attr方法,这个方法有赋值功能却又有取值功能,但是或许这对于开发者来说是难以维护的,但对于用户来说这大大方便了使用,所以在决定使用SRP原则的时候你也就可能会牺牲了代码的复杂度和方便性,优缺点我们容后再提,先说何时分离职责,总结一下就是:

1.不是所有的职责都要分离,比如当两个职责总是同时出现的时候,或许我们可以变通一下不对其进行分离,另外如果两个职责耦合在了一起,可是他们或许永远可不会发生改变,那么也许并不是那么着急去分离他们,在代码重构时在分离他们或许也不迟。

2.要在方便性和稳定相之间做出取舍,不要一成不变的遵守规则,有时候你在选择了SEP的同时,重构代码使其变得复杂,失去了使用的方便以及一定程度的美观。


所以显而易见,SRP的优点毋庸置疑,分离了职责,使得我们的代码变得易于维护以及复用,更有利于我们的测试人员测试,在以后需要变更的时候至少不会因为改变了一个单一职责对象而影响另一职责出现bug;事物总是有双面性的,在我们分离了职责的同时,这些职责对象也就变得疏远了,如果我们想让他们进行联系无疑也就困难多了,同时SRP也会明显增加代码的复杂程度。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值