JavaScript設(shè)計模式二(單例模式)

JavaScript設(shè)計模式二(單例模式)

這邊文章主要是JavaScript中的單例模式
定義:

保證一個類僅有一個實例,并提供一個訪問它的全局訪問點

其實我們的日常開發(fā)中或多或少的用到了單例模式的方法穷缤。例如我們做Electron開發(fā)的過程中,點擊一個按鈕創(chuàng)建了一個窗口感论,后續(xù)點擊的時候绅项,如果窗口已經(jīng)存在了就focus窗口,否則創(chuàng)建比肄;或者我們經(jīng)常會創(chuàng)建一個定時任務(wù)快耿,同時把定時任務(wù)賦值給一個變量,如果變量不存在就創(chuàng)建芳绩,否則不創(chuàng)建掀亥。但是大多數(shù)情況我們都是利用的是一個變量來控制的。接下來我們看看代碼的實現(xiàn)

實現(xiàn)單例模式

其實上面的介紹我們已經(jīng)說了實現(xiàn)單例模式的思路妥色,就是通過一個變量來控制

var Singleton=function(name) {
    this.name=name;
    this.instance=null;
}
Singleton.prototype.getName=function(){
    console.log(this.name);
}
Singleton.getInstance=function(name) {
    if(!this.instance) {
        this.instance = new Singleton(name);
    }
    return this.instance;
}

//這種寫法借助了this.instance搪花,其實可以不需要

var Singleton = function(name) {
    this.name=name;
}
Singleton.prototype.getName=function(){
    console.log(this.name);
}
Singleton.getInstance=(function(){
    var instance = null;
    return function(name) {
        if(!instance) {
            instance = new Singleton(name);
        }
        return instance;
    };
})();

使用方法:

var a = Singleton.getInstance('a');
var b = Singleton.getInstance('b');
a===b

這種方式實現(xiàn)了我們說的單例模式,但是有一個很明顯的缺點嘹害,就是我們實例化的時候不是使用的new方法來實例化撮竿,而是用的getInstance方法,也就是說我們必須知道這個類是單例類笔呀,才能這樣去用幢踏,這就增加了不透明性。

透明的單例模式

所謂的透明的單例模式许师,就是我們可以像正常的類那樣去new一個單例類房蝉。

var CreateDiv = (function(){
    var instance;
    var CreateDiv = function(html) {
        if (instance) {
            return instance;
        }
        this.html = html;
        this.init();
        return instance = this;
    };
    
    CreateDiv.prototype.init = function() {
        var div = document.createElement('div');
        div.innerHTML = this.html;
        document.body.appendChild('div');
    };
    
    return CreateDiv;
})();

var a = new CreateDiv('div');
var b = new CreateDiv('div');

a===b

之所以能夠通過new來創(chuàng)建一個單例類的實例僚匆,是因為CreateDiv
的返回值是一個構(gòu)造函數(shù),這個構(gòu)造函數(shù)做了兩件事情

  • 創(chuàng)建對象和執(zhí)行init方法
  • 保證只有一個對象

我們可以想象如果需求變成了搭幻,我們需要CreateInput之類咧擂,是不是一直要修改這個類呢?

代理實現(xiàn)單例模式

利用代理就可以很好的解決上面的問題

var CreateDiv = function(html) {
    this.html = html;
    this.init();
}

CreateDiv.prototype.init = function() {
   var div = document.createElement('div');
   div.innerHTML = this.html;
   document.body.appendChild('div');
};

var ProxySingletonCreateDiv = (function(){
    var instance;
    return function(html) {
        if (!instance) {
            instance = new CreateDiv(html);
        }
        return instance;
    }
})();


var a = new ProxySingletonCreateDiv('div');
var b = new ProxySingletonCreateDiv('div');

利用代理類檀蹋,我們遵循了單一職責(zé)的原則松申,讓代理類負責(zé)單例的邏輯,CreateDiv變成一個普通的創(chuàng)建html的類续扔,兩者結(jié)合達到單例模式的效果

JavaScript中的單例模式

JavaScript單例模式的核心是:

確保只有一個實例攻臀,并提供全局訪問

與傳統(tǒng)的面向?qū)ο笳Z言不一樣焕数,JavaScript可以定義全局變量,而且我們通常認(rèn)為全局變量就是一個單例识脆,但是這種使用方式很容易造成命名空間的污染善已,針對這種問題有兩種辦法

  • 使用命名空間
    最簡單的就是使用字面量常量:
var namespace1 = {
    a: function(){},
    b: 'bbbb'
}
  • 利用閉包封裝變量

var user = (function(){
    
    var _user = 'hahaha';
    return {
        setUserName: function(name) {
            _user = name;
        },
        getUserName: function(){
            console.log(_user);
        }
    }
})();

惰性單例

定義:

惰性單例是指需要時才創(chuàng)建的單例

上面的那幾種方法實際上就是惰性單例,但是那些事面向?qū)ο蟮南こ恚覀兛纯碕avaScript中的惰性單例艘包,看一段PC版的代碼吧

let historyWindow = null;
ipc.on(cfg.CHANNEL.LOCAL.CHAT.SEARCH_HISTORY, function(event, arg) {
  if (!historyWindow) {
    historyWindow = new BrowserWindow({
      width: 621,
      height: 540,
      minWidth: 621,
      minHeight: 540,
      frame: false,
      show: false,
    });
    historyWindow.setAutoHideMenuBar(false);
    historyWindow.loadURL('file://' + __dirname + '/../../../client/views/history.html');
    if (process.env.NODE_ENV == 'dev') {
      historyWindow.webContents.openDevTools();
    }
    historyWindow.on('close', function() {
      historyWindow.webContents.closeDevTools();
    });
    historyWindow.on('closed', function() {
      glb.set(cfg.GLB.HISTORY_WINDOW, null);
      glb.remove(cfg.GLB.ADD_MEMBER_WINDOW);
      historyWindow = null;
    });
    historyWindow.webContents.on('did-finish-load', function() {
      glb.set(cfg.GLB.HISTORY_WINDOW, historyWindow);
      historyWindow.show();
      historyWindow.focus();
      historyWindow.webContents.send(cfg.CHANNEL.LOCAL.CHAT.OPEN_HISTORY_WINDOW_RECV, arg);
    });
  } else {
    historyWindow.webContents.send(cfg.CHANNEL.LOCAL.CHAT.OPEN_HISTORY_WINDOW_RECV, arg);
    if (historyWindow.isMinimized()) {
      historyWindow.show();
    } else {
      historyWindow.focus();
    }
  }
});

這段代碼的邏輯是想虎,點擊歷史消息的icon,創(chuàng)建一個歷史消息的彈出框岂却,后面如果繼續(xù)點擊裙椭,就把之前的彈出框focus。

這里其實還有優(yōu)化的空間扫尺,我們知道electron創(chuàng)建一個新的BrowserWindow是很慢的,所以我們創(chuàng)建一次之后你雌,用戶點擊關(guān)閉二汛,其實可以隱藏起來肴颊,并不是實際的關(guān)閉,這樣當(dāng)用戶點擊第二次的時候就省略了創(chuàng)建窗口的過程婿着,直接渲染數(shù)據(jù)就可以醋界。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末形纺,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子蜗字,更是在濱河造成了極大的恐慌脂新,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件级零,死亡現(xiàn)場離奇詭異滞乙,居然都是意外死亡,警方通過查閱死者的電腦和手機亥贸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進店門炕置,熙熙樓的掌柜王于貴愁眉苦臉地迎上來男韧,“玉大人,你說我怎么就攤上這事此虑。” “怎么了朦前?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵鹃操,是天一觀的道長荆隘。 經(jīng)常有香客問我赴背,道長,這世上最難降的妖魔是什么燃观? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任缆毁,我火速辦了婚禮,結(jié)果婚禮上积锅,老公的妹妹穿的比我還像新娘养盗。我一直安慰自己往核,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布聂儒。 她就那樣靜靜地躺著衩婚,像睡著了一般。 火紅的嫁衣襯著肌膚如雪非春。 梳的紋絲不亂的頭發(fā)上缓屠,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天敌完,我揣著相機與錄音,去河邊找鬼什湘。 笑死长赞,一個胖子當(dāng)著我的面吹牛闽撤,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播腹尖,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼热幔,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了近尚?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤戈锻,失蹤者是張志新(化名)和其女友劉穎格遭,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體拒迅,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡她倘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年硬梁,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片屹电。...
    茶點故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡罩息,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出瓷炮,到底是詐尸還是另有隱情,我是刑警寧澤苍狰,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站俐填,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏英融。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一驶悟、第九天 我趴在偏房一處隱蔽的房頂上張望痕鳍。 院中可真熱鬧龙巨,春花似錦、人聲如沸旨别。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽胆屿。三九已至非迹,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間纯趋,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工纯命, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留亿汞,地道東北人揪阿。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓咆畏,卻偏偏與公主長得像吴裤,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子钮蛛,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,612評論 2 350

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理魏颓,服務(wù)發(fā)現(xiàn),斷路器琼开,智...
    卡卡羅2017閱讀 134,637評論 18 139
  • 單例模式(SingletonPattern)一般被認(rèn)為是最簡單柜候、最易理解的設(shè)計模式,也因為它的簡潔易懂渣刷,是項目中最...
    成熱了閱讀 4,231評論 4 34
  • 1 單例模式的動機 對于一個軟件系統(tǒng)的某些類而言矗烛,我們無須創(chuàng)建多個實例。舉個大家都熟知的例子——Windows任務(wù)...
    justCode_閱讀 1,432評論 2 9
  • 第3章 基本概念 3.1 語法 3.2 關(guān)鍵字和保留字 3.3 變量 3.4 數(shù)據(jù)類型 5種簡單數(shù)據(jù)類型:Unde...
    RickCole閱讀 5,106評論 0 21
  • 總結(jié)一下今年感覺還不錯 中的
    7a433e1f1491閱讀 152評論 0 0