目 录CONTENT

文章目录
Go

创建型-单例模式(Singleton Implementation)

Hello!你好!我是村望~!
2023-08-18 / 0 评论 / 0 点赞 / 111 阅读 / 1,179 字
温馨提示:
我不想探寻任何东西的意义,我只享受当下思考的快乐~

创建型-单例模式(Singleton Implementation)

单例模式是一种创建型设计模式,旨在确保一个类只有一个实例,并提供一个全局访问点以访问该实例。

现实生活中的例子:

同一时间只能有一个国家的总统。 无论何时打电话,都必须将同一位总统付诸行动。 这里的总统就是单例。

通俗解释:

确保只有特定类的一个对象被创建。

维基百科:

在软件工程中,单例模式是一种软件设计模式,它将类的实例化限制为一个对象。当仅需要一个对象来协调整个系统的操作时,这非常有用。

这在某些情况下非常有用,例如控制共享资源、管理配置信息、日志记录等。单例模式通常涉及以下几个要素:

  1. 私有构造函数(Private Constructor):确保其他类无法直接实例化该类,只能通过特定的方法获取实例。
  2. 私有静态成员变量(Private Static Member):用于保存唯一实例。
  3. 公有静态方法(Public Static Method):提供对唯一实例的访问。这是获取单例实例的唯一途径。

下面是一个使用 Go 语言实现的单例模式示例:

package main

import (
	"fmt"
	"sync"
)

type Singleton struct {
}

var instance *Singleton
var once sync.Once

func GetInstance() *Singleton {
	once.Do(func() {
		fmt.Println("once") //无论这个GetInstance执行多少次 这个once只会执行一次
		instance = &Singleton{}
	})
	return instance
}

func main() {
	a1 := GetInstance()
	a2 := GetInstance()
	fmt.Println(*a1 == *a2) // true
}

在这个示例中,GetInstance 函数利用了 sync.Once 来保证只有一个实例会被创建。第一次调用 GetInstance 时,sync.Once 会执行其中的代码块,并将 instance 初始化为新的 Singleton 实例。之后的调用将直接返回之前创建的实例。


sync.Once 是 Go 语言标准库中提供的一种线程安全的机制。它可以确保其中的代码块只会在第一次调用时执行一次,之后的调用都会被忽略,从而保证了只有一个线程能够执行其中的代码。

在多线程环境中,sync.Once 使用了内部的锁和原子操作来实现,以确保在多个线程同时尝试执行代码块时,只有一个线程能够成功执行,其他线程会被阻塞。这使得 sync.Once 在实现单例模式等场景时非常有用,能够确保只有一个实例被创建。

使用单例模式时要注意以下几点:

  1. 线程安全性:在多线程环境中,要确保单例模式的实现是线程安全的,以防止并发访问导致的问题。
  2. 懒加载:有时候可能希望单例实例在需要的时候再被创建,这样可以避免不必要的资源消耗。
  3. 全局状态:单例模式引入了全局状态,这可能会增加代码的复杂性和耦合性。谨慎使用单例,确保它适合你的设计。
  4. 测试难度:由于单例模式引入了全局状态,可能会增加单元测试的难度。可以使用依赖注入等技术来缓解这个问题。

饿汉式(Eager Initialization)是单例模式的另一种实现方式

它在类加载的时候就创建了实例,无论是否被使用。

这样可以保证在任何时候都只有一个实例存在。以下是使用 Go 语言实现饿汉式单例模式的示例:

package singleton

type Singleton struct {
	// 你的单例结构体字段
}

var instance = &Singleton{} // 在包加载时就创建实例

func GetInstance() *Singleton {
	return instance
}

自己手动互斥锁来实现懒汉式单例模式

package singleton

import (
	"sync"
)

type Singleton struct {
	// 你的单例结构体字段
}

var instance *Singleton
var mu sync.Mutex

func GetInstance() *Singleton {
	if instance == nil {
		mu.Lock()
		defer mu.Unlock()
		if instance == nil {
			instance = &Singleton{}
		}
	}
	return instance
}

在这个示例中,GetInstance 函数使用了互斥锁 sync.Mutex 来确保在多线程环境中只有一个线程可以创建实例。当第一个线程进入函数时,它会获取锁并创建实例,之后的线程会等待直到锁被释放。这样可以避免在并发情况下出现多个实例的问题。

0

评论区