編寫可維護(hù)性的JavaScript 之設(shè)計模式 (一)

前言

最近這段時間重構(gòu)了一些項目, 期間遇到的最大的問題就是怎樣保證代碼的健壯性。很多情況下由于寫的代碼考慮不完善,使得重構(gòu)的過程中有新的需求加入, 很多原先的邏輯不得不整體推翻重寫。在網(wǎng)上看了很多相關(guān)資料,受益匪淺??偟膩碚f寫代碼也是要有套路的。一個好的套路能夠讓我們的代碼有更好的可讀性,可維護(hù)性,也能提高自身編碼的層次。我看了一些設(shè)計模式有關(guān)的書,發(fā)現(xiàn)很多東西在寫的時候其實是有規(guī)律可循,比如一些常見的設(shè)計模式。在寫代碼的過程中根據(jù)項目的情況加入設(shè)計模式的思想,必將能夠很大程度上提升我們的代碼水平。 曾探《javascript 設(shè)計模式與開發(fā)實踐》這本書寫得非常好。雖然是前幾年出版的,但是里面很多思想一點也不過時。于是我就有了一個想法,以這本書為大綱, 我想通過我的理解將書中的精要簡略的寫出來..

單例模式

所謂單例模式 就是 一個類僅有一個實例并且提供一個它訪問全局的訪問方法

透明單例模式

現(xiàn)在我們有一個需求:在頁面中掉一個方法 始終只創(chuàng)建一個div 。這種場景一般可以應(yīng)用于創(chuàng)建遮罩層這種需求

var createDom = (function(){
     var instance;
var createDom = function( html ){ 
    if ( instance ){
        return instance; 
        }
this.html = html; this.init();
return instance = this;
};
createDom.prototype.init = function(){
    var div = document.createElement( 'div' );
    div.innerHTML = this.html;
    document.body.appendChild( div );
};
return createDom; 
})();
var a = new createDom( 'div1' ); 
var b = new createDom( 'div2' );

alert ( a === b ); // true

單例模式 只有一個核心就是確保只有一個實例,并提供給全局訪問

上面的單例模式是從 “類” 中來展現(xiàn)的 ,在以類為中心的語言中 這是很自然的做法。JS是一門無類型的語言。我們要實現(xiàn)單例模式只要抓住一點就是 只有一個實例 并提供給全局訪問就可以了

全局變量不是單例模式 ,但是在JavaScript開發(fā)中我們經(jīng)常會把 全局變量當(dāng)成單例來使用

例如:

var a = {}

js 聲明全局變量會有很多問題比如 容易被其他模塊篡改,不利于模塊化在ES6 中推出了 let const 這種塊級作用域聲明方法。我們在創(chuàng)建對象以及其方法的過程中最好使用對象的字面量方式如:

let instance = {
    aaa:function(){},
    bbb:function(){}
}

惰性單例模式

前面的例子我們在初始化的時候就進(jìn)行了實例化, 所謂 惰性單例就是我們要在需要的時候才創(chuàng)建對象實例

例子: 登陸彈窗,需求是點擊登陸 彈出彈窗,

   <button id="loginBtn">登錄</button>
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; 
}
})();

document.getElementById( 'loginBtn' ).onclick = function(){ 
    var loginLayer = createLoginLayer();
        loginLayer.style.display = 'block';
};

這個例子,我們點擊的時候才創(chuàng)建 dom實例, 通過閉包, 下一次點擊的時候還是返回之前的實例

通用的惰性單例

上面的代碼很好的實現(xiàn)了一個 我們的需求,但是還是存在一些問題

  • 代碼違反了單一職責(zé)的原則 ,創(chuàng)建對象和管理單例的邏輯都煩剛在createLoginLayer對象內(nèi)部
  • 如果下次我們需要創(chuàng)建頁面中唯一的iframe,或者 script 標(biāo)簽,用來跨域請求數(shù)據(jù),就 必須得如法炮制,把 createLoginLayer 函數(shù)幾乎照抄一遍
    var createIframe= (function(){
         var iframe;
            return function(){
                if ( !iframe){
                    iframe= document.createElement( 'iframe' );
                    iframe.style.display = 'none';
                    document.body.appendChild( iframe);
                }
        return iframe; 
        }
    })();

我們現(xiàn)在需要把不變的分離出來,管理單例的邏輯其實是可以抽象出來的,這個邏輯始終是: 用一個變量來標(biāo)志是否創(chuàng)建過對象,如果是 ,則返回這個已經(jīng)創(chuàng)建好的對象

    var obj;
    if( !obj){
        obj = xxx;
    }

我們來看優(yōu)化后的代碼

//管理單例的邏輯 抽象出來
 var getSingle = function( fn ){
         var result;
         return function(){
         return result || ( result = fn .apply(this, arguments ) );
} };

// 登陸懸浮窗的代碼 
var createLoginLayer = function(){
    var div = document.createElement( 'div' );
    div.innerHTML = '我是登錄浮窗';
    div.style.display = 'none';
    document.body.appendChild( div );
    return div;
  };
var createSingleLoginLayer = getSingle( createLoginLayer );
document.getElementById( 'loginBtn' ).onclick = function(){ 
    var loginLayer = createSingleLoginLayer();
        loginLayer.style.display = 'block';
}; 

// 創(chuàng)建一個iframe 的代碼
var createSingleIframe = getSingle( function(){
    var iframe = document.createElement ( 'iframe' );
    document.body.appendChild( iframe );
    return iframe; 
 });
document.getElementById( 'loginBtn' ).onclick = function(){
     var loginLayer = createSingleIframe();
loginLayer.src = 'http://baidu.com';
};
 

在這個例子中,我們把創(chuàng)建實例對象的職責(zé)和管理單例的職責(zé)分別放置在兩個方法里,這兩 個方法可以獨(dú)立變化而互不影響,當(dāng)它們連接在一起的時候,就完成了創(chuàng)建唯一實例對象的功能, 看起來是一件挺奇妙的事情

本文部分摘錄自 曾探《javascript 設(shè)計模式與開發(fā)實踐》這本書寫得相當(dāng)出彩 強(qiáng)烈推薦

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,724評論 19 139
  • 單例模式(SingletonPattern)一般被認(rèn)為是最簡單、最易理解的設(shè)計模式,也因為它的簡潔易懂,是項目中最...
    成熱了閱讀 4,551評論 4 34
  • 設(shè)計模式匯總 一、基礎(chǔ)知識 1. 設(shè)計模式概述 定義:設(shè)計模式(Design Pattern)是一套被反復(fù)使用、多...
    MinoyJet閱讀 4,098評論 1 15
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,900評論 18 399
  • 首先恭喜戳進(jìn)來閱讀的各位,你們擁有夢想,這真是一件很棒的事情啊。無論你們的夢想是什么,是迎娶白富美出任ceo,亦或...
    雨川閱讀 585評論 0 1

友情鏈接更多精彩內(nèi)容