iT邦幫忙

2023 iThome 鐵人賽

DAY 1
1
自我挑戰組

掘地土撥鼠的設計歷險記系列 第 2

Singleton 單例模式

  • 分享至 

  • xImage
  •  

Singleton 中文為單例模式,其存在的目的就是確保code中使用的物件只會存在一個。
在Go語言中,實現的方式有四種,其中都有一個共同點: 只會實例化一次

Lazy Initialization

  • 透過一個類別,在物件為空時再進行實例化
  • 在平行運算下,可能會造成創建多次的情況,防止上述危險,建議使用 Mutex 進行記憶體加鎖
  • 每次使用時,都需要加解鎖,性能上不是很優

code 如下

package main

import (
 "fmt"
 "sync"
)

type Singleton struct {
   value int
}

var instance *Singleton
var mutex sync.Mutex

func GetInstance() *Singleton {
 
   mutex.Lock()
   defer mutex.Unlock()
   if instance == nil {
      instance = new(Singleton)
      fmt.Println("new instance")
   }
   return instance
}

Eager Initialization

  • 不判斷是物件是否為空值,在類別初始時實例化該物件
  • 缺點 -> 在 import 進來時,記憶體就會被占走

code 如下

package main

import "fmt"

type Singleton struct {
   value int
}

var instance *Singleton

func init() {
   if instance == nil {
      fmt.Println("New instance of Singleton")
      instance = new(Singleton)
   }
}

func GetInstance() *Singleton {
   return instance
}

Double Checking Singleton

  • Lazy Initialization 的優化版本,多了一層驗證物件是否為空,用來避免每次的加解鎖

code 如下

package main

import (
 "fmt"
 "sync"
)

type Singleton struct {
   value int
}

var mutex sync.Mutex
var instance *Singleton

func GetInstance() *Singleton {
   if instance == nil {
      mutex.Lock()
      if instance == nil {
         instance = new(Singleton)
         fmt.Println("New Singleton")
      }
      mutex.Unlock()
   }
   return instance
}

sync.Once Singleton

  • sync.Once 是由 Go標準 Library 提供的一種方法
  • 效果與 Init() 雷同,但有區別,Init() 在類別被 import 時就會執行
  • sync.Once 會等待被使用時才進行

code如下

package main

import (
   "fmt"
   "sync"
)

type Singleton struct {
   value int
}

var once sync.Once
var instance *Singleton

func GetInstance() *Singleton {
   once.Do(func() {
      instance = new(Singleton)
      fmt.Println("New instance of Singleton")
   })
   return instance
}

優缺點分析

優點

  • 可擴展成為工廠模式
  • 可以確保系統的記憶體中只會有一個物件存在,用以提升性能

缺點

  • 非抽象,表示不同的物件都需要去做特別處理,擴展性低
    如果長時間的不使用 singleton 物件時,該記憶體會被視為垃圾資源被回收掉,導致物件為空

總結

綜合上面的筆記,知道Singleton的宗旨為何。
但就code上的層面來說,可以知道:

  • Golang 中 方法要回傳的型態必須在宣告時定義好(與Solidity相似)
  • 我們可以以指標的形式回傳物件,來讓物件保持在同一個記憶體位址上

上一篇
Recamp: UML
下一篇
Factory Method Pattern - 工廠模式
系列文
掘地土撥鼠的設計歷險記11
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言