GoLang设计模式05 - 单例模式

单例模式是什么

单例模式是一种创建型设计模式:单例模式保证一个类仅有一个实例,并提供一个访问它的全局访问点。

为什么要用单例模式

为什么要用单例模式?在系统中某些对象,我们只需要一个全局的,如果每次实例化会浪费资源。所以单例模式可以节约内存,加快对象访问速度,因此单例模式在某些场合适合使用。比如多个模块使用同一个数据源连接对象;比如配置数据可以由一个单例对象统一读取;还有比如日志文件的对象也可以用单例模式。

单例模式怎么实现

我们可以用一个私有的全局变量来保存一个对象,并且提供一个获取对象的方法,在这个方法里面来实现只创建一次。但是要注意多线程的情况,如果多个线程同时访问,也要保证只创建一个对象。这里我们可以用golang的原子操作来实现。我们这里用sync.Once来实现延迟加载,也就是单例模式中的懒汉模式;还有饿汉模式既是初始化的时候就实例对象

 1 package main
 2 
 3 import (
 4     "fmt"
 5     "sync"
 6     "sync/atomic"
 7 )
 8 
 9 type Singleton struct {
10 }
11 
12 //饿汉,最优雅,强烈推荐
13 var instance0 *Singleton
14 
15 func init() {
16     instance0 = new(Singleton)
17 }
18 func GetInstanceHungry() *Singleton {
19     return instance0
20 }
21 
22 //懒汉1,使用sync.Once包
23 var instance1 *Singleton
24 var once sync.Once
25 
26 func GetInstanceLazy() *Singleton {
27     once.Do(func() {
28         instance1 = new(Singleton)
29     })
30     return instance1
31 }
32 
33 //懒汉2,自己解决并发问题,使用sync/atomic包、sync.Mutex包
34 var instance2 *Singleton
35 var lock = new(sync.Mutex)
36 
37 var flag int32
38 
39 func GetInstanceLazy2() *Singleton {
40     if atomic.LoadInt32(&flag) == 1 {
41         return instance2
42     }
43     if instance2 == nil {
44         lock.Lock()
45         defer lock.Unlock()
46         instance2 = new(Singleton)
47         atomic.StoreInt32(&flag, 1)
48     }
49     return instance2
50 }
51 
52 func main() {
53     if GetInstanceLazy2() == GetInstanceLazy2() {
54         fmt.Println("is equal")
55     } else {
56         fmt.Println("not equal")
57     }
58     if GetInstanceLazy() == GetInstanceLazy() {
59         fmt.Println("is equal")
60     } else {
61         fmt.Println("not equal")
62     }
63     if GetInstanceHungry() == GetInstanceHungry() {
64         fmt.Println("is equal")
65     } else {
66         fmt.Println("not equal")
67     }
68 }

 

优点

  1. 为整个系统提供一个全局的访问点,利于管理。
  2. 全局只有一个该对象,节约内存。
  3. 避免了频繁的创建销毁,提示性能。

缺点

  1. 不适用于变化的对象,如果同一类型的对象总是要在不同的用例场景发生变化,单例就会引起数据的错误。
  2. 由于单例模式中没有抽象层,因此单例类的扩展有很大的困难。
posted @ 2023-04-20 18:29  格局打得开  阅读(63)  评论(0)    收藏  举报