單一職責原則之模式的黃金法則

在設計模式中,有着幾條視爲黃金原則,設計模式都是圍繞黃金原則,對代碼或者說是架構設計作出一些相應的調整,長此以往,GoF 4人組,發現其實有些設計思想能夠稱爲模式,能實現代碼複用的好處,從而設計模式出世。其實,這些模式的基石就是黃金原則,因此,接下來會對這些原則進行詳細的解析。今天說一下,單一職責原則。ajax

談談單一職責原則

單一職責原則,英文名叫作SRP.即,Single responsibility principle (裝個逼). 咱們從字面上,差很少已經徹底能夠理解這個原則所要表達的意思。在js中,函數永遠是一等公民,而函數所表明的就是一份職責。 一個函數完成一個功能,最後編織成了咱們的js程序。設計模式

前面差很少把模式基本的梳理了一遍,要知道,每一個模式裏面或多或少會包含一些原則。。。(我編不下去)緩存

說人話呀~~~ 俺們看不懂!!!
客官對不起,小的這就給你上栗子。安全

單一職責與代理

直接來乾貨。在代理模式中,你們還記得這個例子嗎?圖片的加載閉包

在未引入代理模式的時候是這樣寫的架構

var delayload = (function(){
    var img = document.querySelector("#img");
    img.src = "loading.gif";
    var newImg = document.createElement("img");
    newImg.onload = function(){
        img.src = newImg.src;
    }
    return function(src){
        newImg.src = src;
    }
})();
delayload("jimmy.jpg");

咱們分析一下,在delayload裏面存在了兩個原則,一個是給本體的img設置src,還有一個是,虛擬構建一個Img節點來加載圖片,最後在加載完成的時候,修改本體的src. 這樣寫,沒錯,若是在沒有其餘的需求以前,這個代碼能夠算是比較完美的。 可是,你的產經永遠不會這麼一心一意,有時候,會讓你把,等待加載的圖片換掉,有時候。。。app

因此爲了擴展性考慮,咱們能夠參考單一職責原則,修改以下:函數

//將背景圖設置,和圖片加載的src修改分開
var delayload = (function(){
    var img = document.querySelector("#img");
    return {
        setSrc:function(src){
            img.src = src;
        }
    }
})();
var proxy = (function(){
    var img = document.createElement('img');
    img.onload = function(){
        delayload.setSrc(img.src);
    }
    return {
        setSrc:function(src){
            delayload.setSrc("loading.gif");
            img.src = src;
        }
    }
})();
proxy.setSrc("jimmy.jpg");

這樣一方面,對於本體img設置src的功能咱們能夠完美的保留下來。this

單一職責與節點渲染

相信你們都遇到這個問題,向後臺請求數據,而後渲染到頁面上。說具體一點就是,像這樣的url

一本圖書的信息,有他的img,title,author這3部份內容。 咱們的職責就是,向後臺請求相關的數據,而後將數據渲染到頁面。而咱們目前的職責就是兩個,獲取數據,而後渲染數據。

var data = {
    img:"http://7xpsmd.com1.z0.glb.clouddn.com/16-1-24/19756676.jpg",
    title:"JS權威指南",
    author:"David Flaagan"
}

http.getBooks = function(url,callback){
    $.ajax(url)
    .then((data)=>{
        itera(data,callback);
    })
}
//要知道,這裏的data可能不僅一個,咱們須要進行遍歷
var itera = function(data,callback){
    for(var i = 0,book;book = data[i++];){
        callback(data); //渲染data
    }
}
//請求數據,而且渲染數據
http.getBooks("www.example.com",function(){
    console.log("渲染數據");
});

簡單流程是這樣的,從大的方面來看,職責確實只有兩個,可是咱們實現的時候,會發現,本體中嵌套一個for循環,會把添加節點函數帶入,這樣耦合性會增大,因此這裏加了一個迭代器模式,讓迭代器來表示循環,即,個人渲染函數只和迭代器發生關係,而你原來的ajax請求是怎麼實現的我並不清楚。

能夠看出,職責的劃分不是一眼就能看出來的,那怎麼看嘞?

其實,我也不知道,看感受唄,有時候感受來了,擋都擋不住.

獲取單例

上面已經說過了,SRP是在模式應用中,最簡單的一個,一樣也是應用最廣的一個。回想一下,咱們在寫單例的時候,一般的格式是一個閉包+一個變量就over了。

var Weather = function() {}
var getSingle = (function() {
    var single;
    return function(obj) {
        if (single === undefined) {
            return single = obj;
        }
        return single;
    }
})();
var weather1 = getSingle(new Weather());  //原始的Weather
var weather2 = getSingle(new Weather());  //存儲的single

這裏,將單例類和獲取單例的工廠分開來。 工廠能夠無限制使用,單例類也能夠執行他獨特的行爲。 這樣作是極好的。 固然,咱們也能夠創造不一樣的工廠出來。

這個是緩存一個功能函數的結果,應用場景主要在加載額外的模板文件時,使用

var getSingle = function(fn){
    var result;
    return function(){
        return result || (result = fn.apply(this,arguments));
    }
}

AOP之SRP

AOP咱們應該算是閱人無數的級別了, 在不少地方都是用過他,職責鏈模式,裝飾者模式等。而AOP也是完美體現SRP原則的。

首先,他自己的書寫都是符合SRP原則

Function.prototype.before = function(fn){
    var _this = this;
    return function(){
        fn.apply(this,arguments);  //值爲Boolean,表示是否繼續向下傳遞
        return    _this.apply(this,arguments);
    }
}

將AOP的概念抽象化,而後就能夠直接使用beofre。

一般咱們能夠將AOP運用到,修改url參數,傳遞權限的業務上面。 好比,接口的地址原本已經很完美了,可是你的leader是處女座(最討厭處女座),非要給url路由添加幾個token以保證後臺數據的安全。如今有兩條路給你,要麼直接改動路由,要麼可使用AOP進行改動。 爲了過年,我會選擇使用AOP,由於不知道處女座之後會作出什麼傻事來。

function dealUrl(url){
    url+=param.getToken();
}
http.ajax = http.ajax.before(dealUrl);
http.ajax("www.example.com");   //此時的Url = www.example.com?token=23jkfd3kjfdksjfkjds

使用before動態織入後,能夠完美的解決處女座。

如何作到SRP原則

實話說,我真的不知道。 我這裏只有幾條我認爲比較好的經驗給你們,由於若是過度追求設計的話,你的程序複雜度將會爆炸!!!。 在合適的時間,合適的位置使用,這纔是SRP的難點。

說一下,不是用SRP原則的時候把。

  1. 分清行爲和動做。 咱們只是用SRP區分動做,而不過度劃分行爲。行爲就是: 建立div,添加類,修改attr等基本操做。 動做就是 將行爲組合在一塊兒達到的效果,好比發送請求,渲染節點。 這類比較抽象的動做。

  2. 要以第一感受爲主,若是感受這樣劃分職責沒錯,使用SRP恰到好處,那就幹吧。 反正之後自已挖的坑本身也得補回來,要知道,沒有重構過的代碼,永遠是不能看的(說的是我。。。)。

其實有時候,從正面走不行,咱們能夠嘗試一下逆向思惟,想一想,你日常沒有使用SRP原則是何時就能夠了。這樣可以幫助你思惟的發展,也能讓你寫出一手好代碼。

相關文章
相關標籤/搜索