GO设计模式——4、单例模式(创建型)
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
目录
单例模式Singleton Pattern
单例模式Singleton Pattern是一个类只允许创建一个对象或者实例那这个类就是一个单例类这种设计模式就叫作单例设计模式简称单例模式。单例模式的要点有三个一是某个类只能有一个实例二是它必须自行创建这个实例三是它必须自行向整个系统提供这个实例。单例模式通常适用于需要共享资源、管理全局状态或控制某个唯一实例的情况。在开发中单例模式可以帮助我们解决数据结构与操作之间的耦合问题实现代码的复用和扩展。
单例模式的核心思想是通过将类的构造函数私有化防止外部代码直接实例化该类然后提供一个静态方法或全局变量来获取类的唯一实例。具体而言单例模式包含以下几个关键要素1私有的构造函数Private Constructor用于限制类的实例化使其只能在类的内部进行。2静态变量或静态方法Static Variable/Method用于保存类的唯一实例或提供全局访问点。通过将构造函数私有化外部代码无法直接实例化类只能通过静态方法或全局变量来获取类的唯一实例。当第一次获取实例时单例模式会创建一个实例并将其保存起来以供后续调用使用。
优缺点
(1优点
- 在内存里只有一个实例减少了内存的开销尤其是频繁的创建和销毁实例比如管理学院首页页面缓存。
- 避免对资源的多重占用比如写文件操作。
2缺点没有接口不能继承与单一职责原则冲突一个类应该只关心内部逻辑而不关心外面怎么样来实例化。
使用场景
- 要求生产唯一序列号。
- WEB 中的计数器不用每次刷新都在数据库里加一次用单例先缓存起来。
- 创建的一个对象需要消耗的资源过多比如 I/O 与数据库的连接等。
饿汉式和懒汉式单例模式
两种常见实现方式饿汉式单例模式和懒汉式单例模式。饿汉式单例模式适用于在程序初始化时就需要创建实例并且该实例在整个程序生命周期内都需要被使用的情况。例如全局的配置管理器或系统的日志记录器可以使用饿汉式单例模式来确保全局唯一性和一致性。懒汉式单例模式适用于需要延迟实例化的情况即只有在需要时才创建实例。例如某些资源消耗较大的对象或者需要根据运行时的条件来确定具体实例的情况下可以使用懒汉式单例模式。
1. 饿汉式单例模式
饿汉式单例模式是一种在类加载时就创建唯一实例的单例模式。在这种模式下实例在整个程序的生命周期中始终存在无论是否被使用。在GetConfigManager()方法中返回配置管理器的唯一实例。配置管理器包含一个configData字典用于保存配置数据。在程序初始化时创建了配置管理器的实例并通过instance变量保存起来。
饿汉式单例模式代码实现
package main
import "fmt"
type ConfigManager struct {
configData map[string]string
}
var instance = &ConfigManager{
configData: make(map[string]string),
}
func GetConfigManager() *ConfigManager {
return instance
}
func (cm *ConfigManager) Set(key, value string) {
cm.configData[key] = value
}
func (cm *ConfigManager) Get(key string) string {
return cm.configData[key]
}
func main() {
configManager := GetConfigManager()
configManager.Set("key1", "value1")
fmt.Println("key1:", configManager.Get("key1"))
configManager1 := GetConfigManager()
configManager1.Set("key1", "value2")
fmt.Println("key1:", configManager.Get("key1"))
}
2. 懒汉式单例模式
懒汉式单例模式是一种在需要时才创建实例的单例模式。在这种模式下实例的创建延迟到第一次被使用时才进行。使用了sync.Once来确保GetLogger()方法只被执行一次从而保证只有一个实例被创建。日志记录器包含了一个日志列表可以通过AddLog()方法添加日志以及通过PrintLogs()方法打印所有日志。
懒汉式单例模式代码实现
package main
import (
"fmt"
"sync"
)
type Logger struct {
logs []string
}
var instancel *Logger
var once sync.Once
func GetLogger() *Logger {
once.Do(func() {
instancel = &Logger{
logs: []string{},
}
})
return instancel
}
func (l *Logger) AddLog(log string) {
l.logs = append(l.logs, log)
}
func (l *Logger) printLogs() {
for _, log := range l.logs {
fmt.Println(log)
}
}
func main() {
logger := GetLogger()
logger.AddLog("Log 1")
logger.AddLog("log2")
logger1 := GetLogger()
logger1.AddLog("log3")
logger.printLogs()
logger1.printLogs()
}