The responsibility of the Single Responsibility Principle (SRP) is defined as “cause of change”. If we have two incentives to rewrite a method, then the method has two responsibilities. Each responsibility is an axis of change, and if one method takes on too many responsibilities, the more likely it will need to be rewritten as requirements change. At this point, this method is usually an unstable, modify the code is always a dangerous thing, especially when the two job coupled together of the time, a job change could affect the realization of other responsibilities, unexpected damage, the coupling is low cohesion and delicate design. Thus, the SRP principle is: an object (method) does only one thing.

Design patterns using SRP

  • Proxy mode image preloading: By increasing the virtual agent, put preloading images of duties in the proxy object, while the ontology is only responsible for img tag is added to the page, this is it the original duties Function and preloaded pictures add img tags separated on the two objects, the duty of the two objects are only a modified motives. When they change individually, they do not affect other objects
/* myImage = () /* myImage = ()function(){
    var imgNode = document.createElement( 'img' );     
    document.body.appendChild( imgNode );
    return {
        setSrc: function( src ){ imgNode.src = src; }}}) (); MyImage */ 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; }}}) (); proxyImage.setSrc('http://imgcache.qq.com/music/photo/000GGDys0yA0Nk.jpg' );
Copy the code
  • Iterator pattern We have code that iterates through a collection and adds divs to the page with their innerHTML corresponding to the elements in the collection
var appendDiv = function( data ){
    for ( var i = 0, l = data.length; i < l; i++ ){
        var div = document.createElement( 'div'); div.innerHTML = data[ i ]; document.body.appendChild( div ); }}; appendDiv( [ 1, 2, 3, 4, 5, 6 ] );Copy the code

The appendDiv function is simply rendering data, but in this case it also iterates over the aggregated object data

It is necessary to extract the responsibility for traversing data, which is the point of the iterator pattern, which provides a way to access an aggregate object without exposing its internal representation

var each = function( obj, callback ) { 
    var value,
    i = 0,
    length = obj.length,
    isArray = isArraylike( obj );
    if(isArray) {// Iterate over an array of classesfor(; i < length; Callback. call(obj[I], I, obj[I]); }}else {
        for ( i inCallback. 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} );
Copy the code
  • Singleton mode The initial login window lazy singleton
var createLoginLayer = (function(){ 
    var div;
    return function() {if ( !div ){
            div = document.createElement( 'div' ); 
            div.innerHTML = 'I'm logging in to the floating window.'; 
            div.style.display = 'none'; 
            document.body.appendChild( div );
        }
        return div; 
    }
})();
Copy the code

We now encapsulate the responsibility for managing singletons and creating login floats into two methods that can vary independently of each other, and when they are linked together, create a unique login float window

var getSingle = function(fn){// Get singleton var result;return function() {returnresult || ( result = fn .apply(this, arguments ) ); }}; var createLoginLayer =functionVar div = document.createElement(){// create a floating window.'div' ); 
    div.innerHTML = 'I'm logging in to the floating window.'; 
    document.body.appendChild( div );
    returndiv; }; var createSingleLoginLayer = getSingle( createLoginLayer ); var loginLayer1 = createSingleLoginLayer(); var loginLayer2 = createSingleLoginLayer(); alert ( loginLayer1 === loginLayer2 ); / / output:true
Copy the code

When to use SRP?

On the one hand, if two responsibilities always change at the same time as requirements change, there is no need to separate them. In ajax requests, for example, creating an XHR object and sending an XHR request are almost always together, so there is no need to separate the responsibilities of creating an XHR object from those of sending an XHR request. On the other hand, the axis of change in responsibilities only makes sense if they are certain to change. Even if two responsibilities are already coupled but there are no signs that they are changing, then it may not be necessary to actively separate them until code needs to be refactored.

conclusion

The SRP principle has the advantage of reducing the complexity of individual classes or objects and breaking them down into smaller granularity by responsibility, which facilitates code reuse and unit testing. When one responsibility needs to be changed, it does not affect the other responsibilities. However, the SRP principle has some disadvantages, most notably the increased complexity of writing code. When we break objects down into smaller granularity by responsibility, we actually make it harder for them to relate to each other.

Series of articles:

JavaScript Design Patterns and Development Practices