日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當(dāng)前位置:首頁 > 科技  > 軟件

三言兩語說透設(shè)計(jì)模式的藝術(shù)-單例模式

來源: 責(zé)編: 時(shí)間:2023-08-05 11:44:51 4700觀看
導(dǎo)讀寫在前面單例模式是一種常用的軟件設(shè)計(jì)模式,它所創(chuàng)建的對(duì)象只有一個(gè)實(shí)例,且該實(shí)例易于被外界訪問。單例對(duì)象由于只有一個(gè)實(shí)例,所以它可以方便地被系統(tǒng)中的其他對(duì)象共享,從而減少系統(tǒng)中的資源開銷。單例模式單例模式的實(shí)現(xiàn)

寫在前面

單例模式是一種常用的軟件設(shè)計(jì)模式,它所創(chuàng)建的對(duì)象只有一個(gè)實(shí)例,且該實(shí)例易于被外界訪問。單例對(duì)象由于只有一個(gè)實(shí)例,所以它可以方便地被系統(tǒng)中的其他對(duì)象共享,從而減少系統(tǒng)中的資源開銷。RBn28資訊網(wǎng)——每日最新資訊28at.com

單例模式

單例模式的實(shí)現(xiàn)思路是:RBn28資訊網(wǎng)——每日最新資訊28at.com

  1. 構(gòu)造函數(shù)需要被私有化,外部無法直接通過new來創(chuàng)建對(duì)象實(shí)例。
  2. 提供一個(gè)靜態(tài)的公有訪問點(diǎn),用于獲取單例對(duì)象的實(shí)例。
  3. 通過判斷實(shí)例是否已經(jīng)存在來決定創(chuàng)建或直接返回現(xiàn)有實(shí)例。

單例模式的要點(diǎn):RBn28資訊網(wǎng)——每日最新資訊28at.com

  • 某個(gè)類只能有一個(gè)實(shí)例
  • 它必須自行創(chuàng)建實(shí)例
  • 它必須自行向整個(gè)系統(tǒng)提供整個(gè)實(shí)例

我們來看一下使用TypeScript實(shí)現(xiàn)單例模式的代碼示例:RBn28資訊網(wǎng)——每日最新資訊28at.com

class Singleton {  // 私有靜態(tài)屬性,存儲(chǔ)唯一實(shí)例  private static instance: Singleton;  // 私有構(gòu)造函數(shù),防止外部實(shí)例化  private constructor() {}  // 向外部提供能夠共享訪問的唯一實(shí)例  public static getInstance(): Singleton {    if (!Singleton.instance) {      Singleton.instance = new Singleton();    }    return Singleton.instance;  }  // 其他方法和屬性}const s1 = Singleton.getInstance(); const s2 = Singleton.getInstance();console.log(s1 === s2); // true

上面代碼中,Singleton類的構(gòu)造函數(shù)被private修飾,使其無法在類的外部通過new來創(chuàng)建實(shí)例。RBn28資訊網(wǎng)——每日最新資訊28at.com

getInstance方法首先會(huì)判斷實(shí)例是否存在,如果不存在才去新建實(shí)例,如果實(shí)例已存在則直接返回現(xiàn)有實(shí)例。這確保了整個(gè)程序中只會(huì)創(chuàng)建該類的一個(gè)實(shí)例。RBn28資訊網(wǎng)——每日最新資訊28at.com

測(cè)試代碼中,s1和s2實(shí)際上是獲取的是同一個(gè)實(shí)例對(duì)象。RBn28資訊網(wǎng)——每日最新資訊28at.com

圖片圖片RBn28資訊網(wǎng)——每日最新資訊28at.com

單例模式的優(yōu)點(diǎn):RBn28資訊網(wǎng)——每日最新資訊28at.com

  • 對(duì)唯一實(shí)例的受控訪問。
  • 由于單例對(duì)象存放在靜態(tài)變量中,所以可以直接通過類名訪問,簡(jiǎn)單方便。
  • 可以避免對(duì)資源的重復(fù)占用。

單例模式的缺點(diǎn):RBn28資訊網(wǎng)——每日最新資訊28at.com

  • 沒有抽象層,擴(kuò)展困難。
  • 單例類的職責(zé)過重,違反單一職責(zé)原則。
  • 沒有接口,依賴具體實(shí)現(xiàn),導(dǎo)致擴(kuò)展性差。

Singleton單例:在單例類的內(nèi)部實(shí)現(xiàn)只生成一個(gè)實(shí)例,同時(shí)提供一個(gè)靜態(tài)方法getInstance()方法,讓用戶可以訪問它的唯一實(shí)例;為了防止在外部對(duì)單例類實(shí)例化,它的構(gòu)造函數(shù)可見性為private;在單例類內(nèi)部定義了一個(gè)Singleton類型的靜態(tài)屬性instance,作為提供給外部共享訪問的唯一實(shí)例。RBn28資訊網(wǎng)——每日最新資訊28at.com

餓漢式單例類

餓漢式單例類:當(dāng)類被加載時(shí),靜態(tài)屬性instance會(huì)被初始化,此時(shí)類的私有構(gòu)造函數(shù)會(huì)被調(diào)用,單例類的唯一實(shí)例將會(huì)被創(chuàng)建。RBn28資訊網(wǎng)——每日最新資訊28at.com

普通單例模式和餓漢式單例模式的區(qū)別:RBn28資訊網(wǎng)——每日最新資訊28at.com

  • 普通單例模式是在第一次調(diào)用getInstance方法時(shí)才創(chuàng)建實(shí)例對(duì)象。
  • 餓漢式是無論是否調(diào)用都會(huì)在類加載時(shí)就創(chuàng)建實(shí)例對(duì)象。

下面我們使用TypeScript代碼實(shí)現(xiàn)一個(gè)餓漢式單例:RBn28資訊網(wǎng)——每日最新資訊28at.com

class Singleton {  private static instance = new Singleton();    private constructor() {}  public static getInstance() {    return Singleton.instance;  }}const s1 = Singleton.getInstance();const s2 = Singleton.getInstance(); console.log(s1 === s2); // true

餓漢式單例由于在類加載時(shí)就完成了初始化,所以理論上它是線程安全的,在多線程環(huán)境下也能保證單例。RBn28資訊網(wǎng)——每日最新資訊28at.com

但餓漢式也有可能造成不必要的實(shí)例化,如果這個(gè)單例的實(shí)例對(duì)象較大,而客戶端又沒調(diào)用getInstance方法,那就會(huì)浪費(fèi)內(nèi)存。RBn28資訊網(wǎng)——每日最新資訊28at.com

懶漢式單例模式

其實(shí)懶漢式單例模式,就是前面提到的普通單例模式。RBn28資訊網(wǎng)——每日最新資訊28at.com

懶漢式單例模式實(shí)現(xiàn)代碼如下:RBn28資訊網(wǎng)——每日最新資訊28at.com

class Singleton {  private static instance: Singleton;  private constructor() {}  public static getInstance(): Singleton {    if (!Singleton.instance) {      Singleton.instance = new Singleton();    }    return Singleton.instance;   }}

但是,這種實(shí)現(xiàn)方式存在一個(gè)問題,就是在多線程環(huán)境下會(huì)存在安全隱患。RBn28資訊網(wǎng)——每日最新資訊28at.com

如果有兩個(gè)線程A和B,它們同時(shí)調(diào)用 getInstance 方法,并且實(shí)例還沒有被初始化,那么它們會(huì)同時(shí)執(zhí)行 Singleton.instance = new Singleton();這行代碼。RBn28資訊網(wǎng)——每日最新資訊28at.com

這樣就會(huì)導(dǎo)致實(shí)際創(chuàng)建了兩個(gè)實(shí)例,違反了單例模式的初衷。RBn28資訊網(wǎng)——每日最新資訊28at.com

為了使懶漢式單例在多線程中也是安全的,我們可以對(duì)getInstance方法加鎖:RBn28資訊網(wǎng)——每日最新資訊28at.com

class Singleton {  private static instance: Singleton;  private constructor() {}  public static getInstance(): Singleton {    if (!Singleton.instance) {      // 加鎖      lock()        if (!Singleton.instance) {        Singleton.instance = new Singleton();      }      // 釋放鎖       unlock()    }    return Singleton.instance;  }}

這樣當(dāng)一個(gè)線程進(jìn)入該方法時(shí),其它線程就只能等待,直到鎖被釋放后才能進(jìn)入方法。RBn28資訊網(wǎng)——每日最新資訊28at.com

這就確保了單例實(shí)例的唯一性。這里的鎖機(jī)制可以使用互斥量mutex等各種鎖的實(shí)現(xiàn)。RBn28資訊網(wǎng)——每日最新資訊28at.com

以上是關(guān)于懶漢式單例線程安全性問題的一個(gè)補(bǔ)充說明。讓我們的單例模式實(shí)現(xiàn)更加健壯。RBn28資訊網(wǎng)——每日最新資訊28at.com

餓漢式單例與懶漢式單例類比較

  1. 實(shí)例化時(shí)機(jī)不同
  • 懶漢式是在第一次調(diào)用getInstance時(shí)才實(shí)例化Singleton對(duì)象
  • 餓漢式是在類加載時(shí)就實(shí)例化了Singleton對(duì)象
  1. 資源利用效率不同
  • 懶漢式更節(jié)約資源,按需實(shí)例化,如果一直沒有調(diào)用getInstance也不會(huì)實(shí)例化
  • 餓漢式不管是否需要都會(huì)實(shí)例化,如果長(zhǎng)時(shí)間沒有使用就會(huì)浪費(fèi)內(nèi)存
  1. 多線程安全性不同
  • 餓漢式天然是多線程安全的,因?yàn)閷?shí)例在類加載時(shí)就已經(jīng)創(chuàng)建好了
  • 懶漢式需要額外的同步機(jī)制來保證多線程安全
  1. 使用場(chǎng)景不同
  • 懶漢式更適合實(shí)例化過程比較耗時(shí)或耗資源的情況
  • 餓漢式更適合實(shí)例化過程很快且確定會(huì)用到的情況

懶漢式相比餓漢式更加靈活,但需要處理多線程安全問題。餓漢式編寫簡(jiǎn)單但不太高效。RBn28資訊網(wǎng)——每日最新資訊28at.com

在實(shí)際開發(fā)中,我們可以根據(jù)需求選擇合適的實(shí)現(xiàn)方式,也可以采用雙重校驗(yàn)鎖等線程安全的懶漢式實(shí)現(xiàn)。RBn28資訊網(wǎng)——每日最新資訊28at.com

一種更好的單例實(shí)現(xiàn)方式

餓漢式單例類不能實(shí)現(xiàn)延遲加載,不管將來用不用,它始終占據(jù)內(nèi)存;懶漢式單例類線程安全控制繁瑣,而且性能收到影響。對(duì)此,無論是餓漢式單例還是懶漢式單例都在一些問題,使用IoDH(Initialization on Demand Holder)可以結(jié)合兩者的優(yōu)點(diǎn),克服兩者的缺點(diǎn)實(shí)現(xiàn)性能和實(shí)現(xiàn)更優(yōu)的單例模式。RBn28資訊網(wǎng)——每日最新資訊28at.com

IoDH是一種技術(shù)方案,它利用了類的靜態(tài)屬性來實(shí)現(xiàn)延遲加載和線程安全。要實(shí)現(xiàn)IoDH,只需在但李磊中增加靜態(tài)內(nèi)部類即可,在該內(nèi)部類中創(chuàng)建單例對(duì)象,再將該單例對(duì)象通過getInstance()方法返回給外部使用。RBn28資訊網(wǎng)——每日最新資訊28at.com

// 單例服務(wù)接口interface SingletonService {  doSomething(): void; }// 單例服務(wù)類class SingletonServiceImpl implements SingletonService {  doSomething() {    console.log('Doing something...');  }}// IoC容器類class IoCContainer {  private singleton: SingletonService;  constructor() {    this.singleton = new SingletonServiceImpl();  }  getSingleton(): SingletonService {    return this.singleton;  }}// 測(cè)試代碼const container = new IoCContainer();const s1 = container.getSingleton();const s2 = container.getSingleton();console.log(s1 === s2); // true

詳細(xì)解析一下使用IoC容器實(shí)現(xiàn)單例模式的代碼:RBn28資訊網(wǎng)——每日最新資訊28at.com

  1. 定義了單例服務(wù)接口SingletonService,用于規(guī)范單例對(duì)象的操作。
  2. SingletonServiceImpl實(shí)現(xiàn)了該接口,作為單例對(duì)象的具體實(shí)現(xiàn)類。
  3. IoC容器類IoCContainer在內(nèi)部持有SingletonService類型的成員變量singleton。
  4. IoC容器類的構(gòu)造函數(shù)中會(huì)實(shí)例化這個(gè)singleton對(duì)象,確保全局只有這一個(gè)實(shí)例。
  5. getSingleton()方法用來返回這個(gè)singleton實(shí)例。
  6. 在測(cè)試代碼中,從IoC容器中獲取了兩次單例對(duì)象,并比較它們的引用是否相同。
  7. 運(yùn)行結(jié)果證明兩次獲取的確是同一個(gè)對(duì)象引用,即單例。

這樣通過IoC容器管理單例的創(chuàng)建,可以實(shí)現(xiàn):RBn28資訊網(wǎng)——每日最新資訊28at.com

  1. 把單例對(duì)象的創(chuàng)建和生命周期管理轉(zhuǎn)移到IoC容器。
  2. 外部代碼不需要關(guān)心單例內(nèi)部的具體實(shí)現(xiàn),只需要從容器中獲取實(shí)例即可。
  3. 符合單一職責(zé)原則,程序邏輯更清晰。
  4. 有利于代碼的可測(cè)試性,可以通過mock容器進(jìn)行單元測(cè)試。
  5. 擴(kuò)展性較好,如果要切換不同的單例實(shí)現(xiàn),只需要調(diào)整容器中的對(duì)象創(chuàng)建即可。

總結(jié)

單例模式作為一種設(shè)計(jì)模式,由于具有明確的目的、簡(jiǎn)單的結(jié)構(gòu)和易于理解的特點(diǎn),在軟件開發(fā)中使用頻率很高,在許多應(yīng)用程序和框架中都有廣泛應(yīng)用。RBn28資訊網(wǎng)——每日最新資訊28at.com

  1. 單例模式的主要優(yōu)點(diǎn)包括:提供對(duì)唯一實(shí)例的受控訪問,由于全局只存在一個(gè)實(shí)例,因此可以節(jié)約系統(tǒng)資源;允許擴(kuò)展為可變數(shù)量的實(shí)例,既節(jié)約資源又解決過度共享影響性能的問題。
  2. 單例模式的主要缺點(diǎn)包括:沒有抽象層導(dǎo)致擴(kuò)展性差;違反單一職責(zé)原則,將實(shí)例化和業(yè)務(wù)邏輯混合在一起;在支持垃圾回收的運(yùn)行時(shí)環(huán)境下可能導(dǎo)致狀態(tài)丟失。
  3. 使用單例模式的典型場(chǎng)景包括:系統(tǒng)只需要一個(gè)實(shí)例;客戶只能通過一個(gè)公共訪問點(diǎn)獲取實(shí)例;需要節(jié)約資源的頻繁創(chuàng)建銷毀對(duì)象。

總之,單例模式是一種利用率較高的設(shè)計(jì)模式,其限制實(shí)例個(gè)數(shù)的特點(diǎn)可以帶來節(jié)省資源的優(yōu)勢(shì),但也可能導(dǎo)致擴(kuò)展性較弱以及與語言環(huán)境不夠匹配等問題。在軟件設(shè)計(jì)中,開發(fā)者需要權(quán)衡考慮系統(tǒng)的需求和優(yōu)缺點(diǎn),適當(dāng)使用單例模式。RBn28資訊網(wǎng)——每日最新資訊28at.com

RBn28資訊網(wǎng)——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-92-0.html三言兩語說透設(shè)計(jì)模式的藝術(shù)-單例模式

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com

上一篇: 從 Pulsar Client 的原理到它的監(jiān)控面板

下一篇: 分布式系統(tǒng)中的CAP理論,面試必問,你理解了嘛?

標(biāo)簽:
  • 熱門焦點(diǎn)
  • 盧偉冰長(zhǎng)文解析K60至尊版 對(duì)Redmi有著里程碑式的意義

    在今天的Redmi后性能時(shí)代戰(zhàn)略發(fā)布會(huì)結(jié)束之后,Redmi總經(jīng)理盧偉冰又帶來了一篇長(zhǎng)文,詳解了為什么 Redmi 要開啟后性能時(shí)代?為什么選擇和 MediaTek、Pixelworks 深度合作?以及后性
  • 7月安卓手機(jī)性價(jià)比榜:努比亞+紅魔兩款新機(jī)入榜

    7月登場(chǎng)的新機(jī)有努比亞Z50S Pro和紅魔8S Pro,除了三星之外目前唯二的兩款搭載超頻版驍龍8Gen2處理器的產(chǎn)品,而且努比亞和紅魔也一貫有著不錯(cuò)的性價(jià)比,所以在本次的性價(jià)比榜單
  • K8S | Service服務(wù)發(fā)現(xiàn)

    一、背景在微服務(wù)架構(gòu)中,這里以開發(fā)環(huán)境「Dev」為基礎(chǔ)來描述,在K8S集群中通常會(huì)開放:路由網(wǎng)關(guān)、注冊(cè)中心、配置中心等相關(guān)服務(wù),可以被集群外部訪問;圖片對(duì)于測(cè)試「Tes」環(huán)境或者
  • 十個(gè)簡(jiǎn)單但很有用的Python裝飾器

    裝飾器(Decorators)是Python中一種強(qiáng)大而靈活的功能,用于修改或增強(qiáng)函數(shù)或類的行為。裝飾器本質(zhì)上是一個(gè)函數(shù),它接受另一個(gè)函數(shù)或類作為參數(shù),并返回一個(gè)新的函數(shù)或類。它們通常用
  • 微信語音大揭秘:為什么禁止轉(zhuǎn)發(fā)?

    大家好,我是你們的小米。今天,我要和大家聊一個(gè)有趣的話題:為什么微信語音不可以轉(zhuǎn)發(fā)?這是一個(gè)我們經(jīng)常在日常使用中遇到的問題,也是一個(gè)讓很多人好奇的問題。讓我們一起來揭開這
  • Python異步IO編程的進(jìn)程/線程通信實(shí)現(xiàn)

    這篇文章再講3種方式,同時(shí)講4中進(jìn)程間通信的方式一、 Python 中線程間通信的實(shí)現(xiàn)方式共享變量共享變量是多個(gè)線程可以共同訪問的變量。在Python中,可以使用threading模塊中的L
  • 小米汽車電池信息疑似曝光:容量101kWh,支持800V高壓快充

    7月14日消息,今日一名博主在社交媒體發(fā)布了一張疑似小米汽車電池信息的照片,顯示該電池包正是寧德時(shí)代麒麟電池,容量為101kWh,電壓為726.7V,可以預(yù)測(cè)小
  • 三星Galaxy Z Fold/Flip 5國(guó)行售價(jià)曝光 :最低7499元/12999元起

    據(jù)官方此前宣布,三星將于7月26日也就是明天在韓國(guó)首爾舉辦Unpacked活動(dòng),屆時(shí)將帶來帶來包括Galaxy Buds 3、Galaxy Watch 6、Galaxy Tab S9、Galaxy
  • SN570 NVMe SSD固態(tài)硬盤 價(jià)格與性能兼具

    SN570 NVMe SSD固態(tài)硬盤是西部數(shù)據(jù)發(fā)布的最新一代WD Blue系列的固態(tài)硬盤,不僅閃存技術(shù)更為精進(jìn),性能也得到了進(jìn)一步的躍升。WD Blue SN570 NVMe SSD的包裝外
Top 主站蜘蛛池模板: 阳东县| 天峻县| 含山县| 黄梅县| 宣威市| 岚皋县| 潞西市| 慈利县| 嵊州市| 河北区| 东平县| 和平区| 阳朔县| 化隆| 大冶市| 子洲县| 云霄县| 江油市| 合阳县| 曲阳县| 潜江市| 宜城市| 大英县| 衡阳市| 济宁市| 广宁县| 荣成市| 容城县| 青海省| 大理市| 新丰县| 靖江市| 凉城县| 台东市| 留坝县| 静乐县| 南丹县| 关岭| 潼南县| 沙田区| 新乡县|