在設計模式中,有着幾條視爲黃金原則,設計模式都是圍繞黃金原則,對代碼或者說是架構設計作出一些相應的調整,長此以往,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咱們應該算是閱人無數的級別了, 在不少地方都是用過他,職責鏈模式,裝飾者模式等。而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區分動做,而不過度劃分行爲。行爲就是: 建立div,添加類,修改attr等基本操做。 動做就是 將行爲組合在一塊兒達到的效果,好比發送請求,渲染節點。 這類比較抽象的動做。
要以第一感受爲主,若是感受這樣劃分職責沒錯,使用SRP恰到好處,那就幹吧。 反正之後自已挖的坑本身也得補回來,要知道,沒有重構過的代碼,永遠是不能看的(說的是我。。。)。
其實有時候,從正面走不行,咱們能夠嘗試一下逆向思惟,想一想,你日常沒有使用SRP原則是何時就能夠了。這樣可以幫助你思惟的發展,也能讓你寫出一手好代碼。