3艾少、單例模式

一象颖、概念

保證一個類僅有一個實例,并提供一個訪問它的全局訪問點姆钉,這樣的模式就叫做單例模式说订。

單例模式是設(shè)計模式中相對較為容易理解、容易上手的一種模式潮瓶,同時因為其具有廣泛的應(yīng)用場景陶冷,也是面試題里的常客毯辅。

二埂伦、實現(xiàn)思路

現(xiàn)在我們先不考慮單例模式的應(yīng)用場景,單看它的實現(xiàn)思恐,思考這樣一個問題:如何才能保證一個類僅有一個實例沾谜? 一般情況下膊毁,當(dāng)我們創(chuàng)建了一個類(本質(zhì)是構(gòu)造函數(shù))后,可以通過new關(guān)鍵字調(diào)用構(gòu)造函數(shù)進而生成任意多的實例對象基跑。像這樣:

class SingleDog {
  show() {
    console.log("我是一個單例對象");
  }
}

const s1 = new SingleDog();
const s2 = new SingleDog();

// false
s1 === s2

我們先 new 了一個 s1婚温,又 new 了一個 s2,很明顯 s1 和 s2 之間沒有任何瓜葛媳否,兩者是相互獨立的對象栅螟,各占一塊內(nèi)存空間。而單例模式想要做到的是篱竭,不管我們嘗試去創(chuàng)建多少次力图,它都只給你返回第一次所創(chuàng)建的那唯一的一個實例。
要做到這一點掺逼,就需要構(gòu)造函數(shù)具備判斷自己是否已經(jīng)創(chuàng)建過一個實例的能力吃媒。我們現(xiàn)在把這段判斷邏輯寫成一個靜態(tài)方法(其實也可以直接寫入構(gòu)造函數(shù)的函數(shù)體里):

三、簡單demo

class SingleDog {
  show() {
    console.log("我是一個單例對象");
  }
  static getInstance() {
    // 判斷是否已經(jīng)new過1個實例
    if (!SingleDog.instance) {
      // 若這個唯一的實例不存在吕喘,那么先創(chuàng)建它
      SingleDog.instance = new SingleDog();
    }
    // 如果這個唯一的實例已經(jīng)存在赘那,則直接返回
    return SingleDog.instance;
  }
}

const s1 = SingleDog.getInstance()
const s2 = SingleDog.getInstance()

除了以上這種實現(xiàn)方法,也可以利用閉包來實現(xiàn):

class SingleDog {
  show() {
    console.log("我是一個單例對象")
  }
}

SingleDog.getInstance = (function () {
  // 定義自由變量instance兽泄,模擬私有變量
  let instance = null
  return function () {
    // 判斷自由變量是否為null
    if (!instance) {
      // 如果為null則new出唯一實例
      instance = new SingleDog();
    }
    return instance;
  }
})()

const res = SingleDog.getInstance()
console.log(res.show())

四漓概、擴展

1.Vuex中的單例模式

Vuex 使用單一狀態(tài)樹漾月,用一個對象就包含了全部的應(yīng)用層級狀態(tài)病梢。至此它便作為一個“唯一數(shù)據(jù)源 (SSOT)”而存在。這也意味著梁肿,每個應(yīng)用將僅僅包含一個 store 實例蜓陌。單一狀態(tài)樹讓我們能夠直接地定位任一特定的狀態(tài)片段,在調(diào)試的過程中也能輕易地取得整個當(dāng)前應(yīng)用狀態(tài)的快照吩蔑。 ——Vuex官方文檔

在Vue中钮热,組件之間是獨立的,組件間通信最常用的辦法是 props(限于父組件和子組件之間的通信)烛芬,稍微復(fù)雜一點的(比如兄弟組件間的通信)我們通過自己實現(xiàn)簡單的事件監(jiān)聽函數(shù)也能解決掉隧期。

但當(dāng)組件非常多、組件間關(guān)系復(fù)雜赘娄、且嵌套層級很深的時候仆潮,這種原始的通信方式會使我們的邏輯變得復(fù)雜難以維護。這時最好的做法是將共享的數(shù)據(jù)抽出來遣臼、放在全局性置,供組件們按照一定的的規(guī)則去存取數(shù)據(jù),保證狀態(tài)以一種可預(yù)測的方式發(fā)生變化揍堰。于是便有了 Vuex鹏浅,這個用來存放共享數(shù)據(jù)的唯一數(shù)據(jù)源嗅义,就是 Store。

Vuex如何確保Store的唯一性

我們先來看看如何在項目中引入 Vuex:

// 安裝vuex插件
Vue.use(Vuex);

// 將store注入到Vue實例中
new Vue({
  el: "#app",
  store,
})

通過調(diào)用Vue.use()方法隐砸,我們安裝了 Vuex 插件之碗。Vuex 插件是一個對象,它在內(nèi)部實現(xiàn)了一個 install 方法凰萨,這個方法會在插件安裝時被調(diào)用继控,從而把 Store 注入到Vue實例里去。也就是說每 install 一次胖眷,都會嘗試給 Vue 實例注入一個 Store

在 install 方法里武通,有一段邏輯和我們樓上的 getInstance 非常相似的邏輯:

let Vue // 這個Vue的作用和樓上的instance作用一樣
...

export function install (_Vue) {
  // 判斷傳入的Vue實例對象是否已經(jīng)被install過Vuex插件(是否有了唯一的state)
  if (Vue && _Vue === Vue) {
    if (process.env.NODE_ENV !== 'production') {
      console.error(
        '[vuex] already installed. Vue.use(Vuex) should be called only once.'
      )
    }
    return
  }
  // 若沒有,則為這個Vue實例對象install一個唯一的Vuex
  Vue = _Vue
  // 將Vuex的初始化邏輯寫進Vue的鉤子函數(shù)里
  applyMixin(Vue)
}

以上便是 Vuex 源碼中單例模式的實現(xiàn)辦法了珊搀,套路可以說和我們的getInstance如出一轍冶忱。通過這種方式,可以保證一個 Vue 實例(即一個 Vue 應(yīng)用)只會被 install 一次 Vuex 插件境析,所以每個 Vue 實例只會擁有一個全局的 Store囚枪。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市劳淆,隨后出現(xiàn)的幾起案子链沼,更是在濱河造成了極大的恐慌,老刑警劉巖沛鸵,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件括勺,死亡現(xiàn)場離奇詭異,居然都是意外死亡曲掰,警方通過查閱死者的電腦和手機疾捍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來栏妖,“玉大人乱豆,你說我怎么就攤上這事〉踔海” “怎么了宛裕?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長论泛。 經(jīng)常有香客問我揩尸,道長,這世上最難降的妖魔是什么孵奶? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任疲酌,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘朗恳。我一直安慰自己湿颅,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布粥诫。 她就那樣靜靜地躺著油航,像睡著了一般。 火紅的嫁衣襯著肌膚如雪怀浆。 梳的紋絲不亂的頭發(fā)上谊囚,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天,我揣著相機與錄音执赡,去河邊找鬼镰踏。 笑死,一個胖子當(dāng)著我的面吹牛沙合,可吹牛的內(nèi)容都是我干的奠伪。 我是一名探鬼主播,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼首懈,長吁一口氣:“原來是場噩夢啊……” “哼绊率!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起究履,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤滤否,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后最仑,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體藐俺,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年盯仪,在試婚紗的時候發(fā)現(xiàn)自己被綠了紊搪。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蜜葱。...
    茶點故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡全景,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出牵囤,到底是詐尸還是另有隱情爸黄,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布揭鳞,位于F島的核電站炕贵,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏野崇。R本人自食惡果不足惜称开,卻給世界環(huán)境...
    茶點故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧鳖轰,春花似錦清酥、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至昆雀,卻和暖如春辱志,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背狞膘。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工揩懒, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人挽封。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓旭从,卻偏偏與公主長得像,于是被迫代替她去往敵國和親场仲。 傳聞我的和親對象是個殘疾皇子和悦,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,779評論 2 354

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

  • 對于系統(tǒng)的一些功能組件鸽素,有一個即可,例如數(shù)據(jù)庫連接池亦鳞,線程池馍忽。。燕差。全局唯一遭笋。想要控制住對象的創(chuàng)建就用到了單例模式。...
    hgfsrui閱讀 328評論 0 0
  • 單例模式(Singleton Pattern)是 Java 中最簡單的設(shè)計模式之一徒探。這種類型的設(shè)計模式屬于創(chuàng)建型模...
    dinel閱讀 367評論 0 0
  • 單例模式:一種創(chuàng)建型設(shè)計模式 應(yīng)用場景:日志系統(tǒng) 瓦呼。一個項目中應(yīng)該只有一個日志系統(tǒng),則應(yīng)當(dāng)確保日志對象只能被創(chuàng)建一...
    JeremyYv閱讀 587評論 0 4
  • 前言 Singleton 模式解決問題十分常見测暗,我們怎樣去創(chuàng)建一個唯一的變量(對象)央串?在基于對象的設(shè)計中我們可以通...
    a621761c7f89閱讀 80評論 0 1
  • 介紹 單例模式(Singleton Pattern)是最簡單的設(shè)計模式之一。這種類型的設(shè)計模式屬于創(chuàng)建型模式碗啄,它提...
    沐深閱讀 885評論 0 0