Golang設計模式-單例模式

一.介紹

意圖:保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。

主要解決:一個全局使用的類頻繁地創建與銷燬。

何時使用:當您想控制實例數目,節省系統資源的時候。

如何解決:判斷系統是否已經有這個單例,如果有則返回,如果沒有則創建。

關鍵代碼:構造函數是私有的。

二.代碼

2.1 懶漢模式

type singleton struct{}
var ins *singleton
func GetIns() *singleton{
    if ins == nil {
      ins = &singleton{}
    }
    return ins
}

缺點:非協程安全。當正在創建時,有協程來訪問此時ins = nil就會再創建,單例類就會有多個實例了。

2.2 餓漢模式

type singleton struct{}
var ins *singleton = &singleton{}
func GetIns() *singleton{
     return ins
}

缺點:如果singleton創建初始化比較複雜耗時時,加載時間會延長。

2.3 懶漢加鎖

type singleton struct{}
var ins *singleton
var mu sync.Mutex
func GetIns() *singleton{
    mu.Lock()
    defer mu.Unlock()
    if ins == nil {
       ins = &singleton{}
    }
    return ins
}

缺點:雖然解決併發的問題,但每次加鎖是要付出代價的

2.4 雙重鎖

type singleton struct{}
var ins *singleton
var mu sync.Mutex
func GetIns() *singleton{  
   if ins == nil {
      mu.Lock()
       defer mu.Unlock()
       if ins == nil {
        ins = &singleton{}
       }
    }
    return ins
}

2.5 sync.Once實現

type singleton struct{}
var ins *singleton
var once sync.Once
func GetIns() *singleton {
    once.Do(func(){
       ins = &singleton{}
    })
    return ins
}

三.優缺點

優點:

  • 在內存裏只有一個實例,減少了內存的開銷,尤其是頻繁的創建和銷燬實例(比如管理學院首頁頁面緩存)。
  • 避免對資源的多重佔用(比如寫文件操作)。

缺點:沒有接口,不能繼承,與單一職責原則衝突,一個類應該只關心內部邏輯,而不關心外面怎麼樣來實例化。

四.使用場景

  • 要求生產唯一序列號。
  • WEB 中的計數器,不用每次刷新都在數據庫里加一次,用單例先緩存起來。
  • 創建的一個對象需要消耗的資源過多,比如 I/O 與數據庫的連接等。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章