欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Go設(shè)計模式之單例模式圖文詳解

 更新時間:2023年07月26日 08:30:12   作者:demo007x  
單例模式是一種創(chuàng)建型設(shè)計模式,讓你能夠保證一個類只有一個實例,并提供一個訪問該實例的全局節(jié)點,本文就通過圖文給大家介紹一下Go的單例模式,需要的朋友可以參考下

單例模式.

問題

單例模式同時解決了兩個問題, 所以違反了單一職責(zé)原則:

  • 保證一個類只有一個實例。 為什么會有人想要控制一個類所擁有的實例數(shù)量? 最常見的原因是控制某些共享資源 (例如數(shù)據(jù)庫或文件) 的訪問權(quán)限。

    它的運作方式是這樣的: 如果你創(chuàng)建了一個對象, 同時過一會兒后你決定再創(chuàng)建一個新對象, 此時你會獲得之前已創(chuàng)建的對象, 而不是一個新對象。

    注意, 普通構(gòu)造函數(shù)無法實現(xiàn)上述行為, 因為構(gòu)造函數(shù)的設(shè)計決定了它必須總是返回一個新對象。

客戶端甚至可能沒有意識到它們一直都在使用同一個對象。

  • 為該實例提供一個全局訪問節(jié)點。 還記得你 (好吧, 其實是我自己) 用過的那些存儲重要對象的全局變量嗎? 它們在使用上十分方便, 但同時也非常不安全, 因為任何代碼都有可能覆蓋掉那些變量的內(nèi)容, 從而引發(fā)程序崩潰。

    和全局變量一樣, 單例模式也允許在程序的任何地方訪問特定對象。 但是它可以保護(hù)該實例不被其他代碼覆蓋。

    還有一點: 你不會希望解決同一個問題的代碼分散在程序各處的。 因此更好的方式是將其放在同一個類中, 特別是當(dāng)其他代碼已經(jīng)依賴這個類時更應(yīng)該如此。

如今, 單例模式已經(jīng)變得非常流行, 以至于人們會將只解決上文描述中任意一個問題的東西稱為單例。

解決方案

所有單例的實現(xiàn)都包含以下兩個相同的步驟:

  • 將默認(rèn)構(gòu)造函數(shù)設(shè)為私有, 防止其他對象使用單例類的 new運算符。
  • 新建一個靜態(tài)構(gòu)建方法作為構(gòu)造函數(shù)。 該函數(shù)會 “偷偷” 調(diào)用私有構(gòu)造函數(shù)來創(chuàng)建對象, 并將其保存在一個靜態(tài)成員變量中。 此后所有對于該函數(shù)的調(diào)用都將返回這一緩存對象。

如果你的代碼能夠訪問單例類, 那它就能調(diào)用單例類的靜態(tài)方法。 無論何時調(diào)用該方法, 它總是會返回相同的對象。

真實世界類比

政府是單例模式的一個很好的示例。 一個國家只有一個官方政府。 不管組成政府的每個人的身份是什么, “某政府” 這一稱謂總是鑒別那些掌權(quán)者的全局訪問節(jié)點。

單例模式結(jié)構(gòu)

  • 單例 (Singleton) 類聲明了一個名為 get­Instance獲取實例的靜態(tài)方法來返回其所屬類的一個相同實例。

    單例的構(gòu)造函數(shù)必須對客戶端 (Client) 代碼隱藏。 調(diào)用 獲取實例方法必須是獲取單例對象的唯一方式。

偽代碼

在本例中, 數(shù)據(jù)庫連接類即是一個單例。 該類不提供公有構(gòu)造函數(shù), 因此獲取該對象的唯一方式是調(diào)用 獲取實例方法。 該方法將緩存首次生成的對象, 并為所有后續(xù)調(diào)用返回該對象。

// 數(shù)據(jù)庫類會對`getInstance(獲取實例)`方法進(jìn)行定義以讓客戶端在程序各處
// 都能訪問相同的數(shù)據(jù)庫連接實例。
class Database is
    // 保存單例實例的成員變量必須被聲明為靜態(tài)類型。
    private static field instance: Database
    // 單例的構(gòu)造函數(shù)必須永遠(yuǎn)是私有類型,以防止使用`new`運算符直接調(diào)用構(gòu)
    // 造方法。
    private constructor Database() is
        // 部分初始化代碼(例如到數(shù)據(jù)庫服務(wù)器的實際連接)。
        // ……
    // 用于控制對單例實例的訪問權(quán)限的靜態(tài)方法。
    public static method getInstance() is
        if (Database.instance == null) then
            acquireThreadLock() and then
                // 確保在該線程等待解鎖時,其他線程沒有初始化該實例。
                if (Database.instance == null) then
                    Database.instance = new Database()
        return Database.instance
    // 最后,任何單例都必須定義一些可在其實例上執(zhí)行的業(yè)務(wù)邏輯。
    public method query(sql) is
        // 比如應(yīng)用的所有數(shù)據(jù)庫查詢請求都需要通過該方法進(jìn)行。因此,你可以
        // 在這里添加限流或緩沖邏輯。
        // ……
class Application is
    method main() is
        Database foo = Database.getInstance()
        foo.query("SELECT ……")
        // ……
        Database bar = Database.getInstance()
        bar.query("SELECT ……")
        // 變量 `bar` 和 `foo` 中將包含同一個對象。

單例模式適合應(yīng)用場景

如果程序中的某個類對于所有客戶端只有一個可用的實例, 可以使用單例模式。

單例模式禁止通過除特殊構(gòu)建方法以外的任何方式來創(chuàng)建自身類的對象。 該方法可以創(chuàng)建一個新對象, 但如果該對象已經(jīng)被創(chuàng)建, 則返回已有的對象。

如果你需要更加嚴(yán)格地控制全局變量, 可以使用單例模式。

單例模式與全局變量不同, 它保證類只存在一個實例。 除了單例類自己以外, 無法通過任何方式替換緩存的實例。

請注意, 你可以隨時調(diào)整限制并設(shè)定生成單例實例的數(shù)量, 只需修改 獲取實例方法, 即 getInstance 中的代碼即可實現(xiàn)。

實現(xiàn)方式

  • 在類中添加一個私有靜態(tài)成員變量用于保存單例實例。
  • 聲明一個公有靜態(tài)構(gòu)建方法用于獲取單例實例。
  • 在靜態(tài)方法中實現(xiàn)"延遲初始化"。 該方法會在首次被調(diào)用時創(chuàng)建一個新對象, 并將其存儲在靜態(tài)成員變量中。 此后該方法每次被調(diào)用時都返回該實例。
  • 將類的構(gòu)造函數(shù)設(shè)為私有。 類的靜態(tài)方法仍能調(diào)用構(gòu)造函數(shù), 但是其他對象不能調(diào)用。
  • 檢查客戶端代碼, 將對單例的構(gòu)造函數(shù)的調(diào)用替換為對其靜態(tài)構(gòu)建方法的調(diào)用。

單例模式優(yōu)缺點

  • 你可以保證一個類只有一個實例。

  • 你獲得了一個指向該實例的全局訪問節(jié)點。

  • 僅在首次請求單例對象時對其進(jìn)行初始化。

  • 違反了單一職責(zé)原則。 該模式同時解決了兩個問題。

  • 單例模式可能掩蓋不良設(shè)計, 比如程序各組件之間相互了解過多等。

  • 該模式在多線程環(huán)境下需要進(jìn)行特殊處理, 避免多個線程多次創(chuàng)建單例對象。

  • 單例的客戶端代碼單元測試可能會比較困難, 因為許多測試框架以基于繼承的方式創(chuàng)建模擬對象。 由于單例類的構(gòu)造函數(shù)是私有的, 而且絕大部分語言無法重寫靜態(tài)方法, 所以你需要想出仔細(xì)考慮模擬單例的方法。 要么干脆不編寫測試代碼, 或者不使用單例模式。

golang代碼示例

Go設(shè)計模式之單例模式講解和代碼示例_Golang_腳本之家 (jb51.net)

到此這篇關(guān)于Go設(shè)計模式之單例模式圖文詳解的文章就介紹到這了,更多相關(guān)Go單例模式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 如何用golang運行第一個項目

    如何用golang運行第一個項目

    這篇文章主要介紹了如何用golang運行第一個項目,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • Go語言類型轉(zhuǎn)換及問題探討

    Go語言類型轉(zhuǎn)換及問題探討

    本文探討了Go語言中的類型轉(zhuǎn)換機(jī)制,特別是在使用atomic.Pointer和unsafe時可能引發(fā)的問題,通過深入分析Go語言的類型轉(zhuǎn)換規(guī)則,如數(shù)值類型間轉(zhuǎn)換、字符串與byte/rune切片轉(zhuǎn)換、slice與數(shù)組轉(zhuǎn)換,以及底層類型相同時的轉(zhuǎn)換,文章最后給出了一些在Go中使用類型轉(zhuǎn)換的建議
    2024-10-10
  • Go泛型實戰(zhàn)教程之如何在結(jié)構(gòu)體中使用泛型

    Go泛型實戰(zhàn)教程之如何在結(jié)構(gòu)體中使用泛型

    這篇文章主要介紹了Go泛型實戰(zhàn)教程之如何在結(jié)構(gòu)體中使用泛型,根據(jù)Go泛型使用的三步曲提到的:類型參數(shù)化、定義類型約束、類型實例化我們一步步來定義我們的緩存結(jié)構(gòu)體,需要的朋友可以參考下
    2022-07-07
  • Go 如何使用原始套接字捕獲網(wǎng)卡流量

    Go 如何使用原始套接字捕獲網(wǎng)卡流量

    為了減少對環(huán)境的依賴可以使用原始套接字捕獲網(wǎng)卡流量,然后使用?gopacket?的協(xié)議解析功能,這樣就省去了解析這部分的工作量,正確性也可以得到保證,同時 CGO 也可以關(guān)閉,這篇文章主要介紹了Go 使用原始套接字捕獲網(wǎng)卡流量,需要的朋友可以參考下
    2024-07-07
  • golang與非golang程序探測beyla源碼解讀

    golang與非golang程序探測beyla源碼解讀

    這篇文章主要為大家介紹了beyla源碼解讀之golang與非golang程序的探測實例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • Go語言實現(xiàn)的最簡單數(shù)獨解法

    Go語言實現(xiàn)的最簡單數(shù)獨解法

    前面給大家介紹過使用javascript實現(xiàn)的簡單的數(shù)獨解法,小伙伴們都非常喜歡,今天我們再來分享一則go語言實現(xiàn)的簡單的數(shù)獨解法,有需要的小伙伴來參考下。
    2015-03-03
  • Go項目分層下的最佳error處理方式分享

    Go項目分層下的最佳error處理方式分享

    這篇文章主要來和大家一起探討?Go?項目分層下的最佳?error?處理方式,準(zhǔn)備好了嗎?準(zhǔn)備一杯你最喜歡的飲料或茶,隨著本文一探究竟吧
    2023-06-06
  • 解決go build不去vendor下查找包的問題

    解決go build不去vendor下查找包的問題

    這篇文章主要介紹了解決go build不去vendor下查找包的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • Golang二維數(shù)組的使用方式

    Golang二維數(shù)組的使用方式

    之前給大家講過很多二維數(shù)組的知識,今天重點給大家介紹Golang二維數(shù)組的使用方式,通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2021-05-05
  • 淺談用Go構(gòu)建不可變的數(shù)據(jù)結(jié)構(gòu)的方法

    淺談用Go構(gòu)建不可變的數(shù)據(jù)結(jié)構(gòu)的方法

    這篇文章主要介紹了用Go構(gòu)建不可變的數(shù)據(jù)結(jié)構(gòu)的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09

最新評論