网站 备案规定,桦南县建设局网站,单位建网站怎么做,佛山知名营销网站开发定义
一个类只允许创建一个对象或实例#xff0c;而且自行实例化并向整个系统提供该实例#xff0c;这个类就是一个单例类#xff0c;它提供全局访问的方法。这种设计模式叫单例设计模式#xff0c;简称单例模式。
单例模式的要点#xff1a;
某个类只能有一个实例必须…定义
一个类只允许创建一个对象或实例而且自行实例化并向整个系统提供该实例这个类就是一个单例类它提供全局访问的方法。这种设计模式叫单例设计模式简称单例模式。
单例模式的要点
某个类只能有一个实例必须自行创建该实例必须自行向整个系统提供该实例 时序图
用处
从业务概念上来看有些数据在系统中只应该保留一份就比较适合设计为单例类。比如系统的配置信息。
使用场景
系统只需要一个实例对象比如唯一的序列号生成器业务方面或是考虑到资源消耗太大而只允许创建一个对象客户调用类的单个实例只允许使用一个公共访问点除了该公共访问点外不能通过其他途径访问该实例
优缺点
优点
提供了对唯一实例的受控访问因为在系统的内存里只存在一个对象所以可以节约系统资源尤其是一些需要频繁创建和销毁的对象允许可变数目的实例基于单例模式进行扩展
缺点
没有抽象层很难扩展职责过重在一定程度上违背了“单一职责原则”。因为单例类既充当了工厂角色提供了工厂方法同时又充当了产品角色包含一些业务方法将产品的创建和产品的本身的功能融合到一起。
单例模式的唯一性
进程间唯一默认单例模式的唯一性就是基于进程的唯一性。因为编写的代码成为可执行文件后当运行该可执行文件时操作系统会启动一个进程将该可执行文件从磁盘加载到自己的进程地址空间该进程依次执行文件中的代码比如代码里有一个创建student对象的语句进程就会在地址空间里创建一个student对象。如果在一个进程中创建另一个进程操作系统会给新进程分配新的地址空间而且将旧地址空间的内容拷贝一份包括代码和数据这样新进程里有且只有一个student对象旧进程里也有且只有一个student但是这两个对象并不是同一个对象。线程间唯一通过获取线程id来实现。但是在golang里主要使用协程而且协程的id并不会暴露出来。集群环境间唯一多进程通过外部共享存储的锁进行如文件。将单例对象序列化后存储到外部共享存储区里比如文件进程在使用该单例对象的时候需要对该单例对象加锁避免其他进程再获取然后将该对象加载到内存里反序列化为单例对象使用完后还要从内存里删除再存储回外部共享存储区并释放锁。
如何实现
构造函数是private访问权限考虑对象创建时的线程安全问题考虑是否支持延迟加载考虑getInstance的性能问题比如是否有加锁等
实现方式
饿汉式
在类加载的时候实例就已经创建好了实例的创建过程线程安全不支持延迟加载
有两种实现方式第一种是定义全局变量的时候创建实例第二种是采用包的init函数创建实例
注意这里的Singleton类型也要是大写字母开头的因为GetInstance方法是大写字母开头表明包外可访问那么该方法的返回值也需要包外可访问。
package singleton// 单例模式 饿汉式实现
type Singleton struct{}var singleton *Singleton//1.全局变量的实现方式
//var singleton1 Singleton{}
//2. 包的init函数实现方式
func init() {singleton Singleton{}
}func GetInstance() *Singleton {return singleton
}
懒汉式
在获取实例的时候再去创建实例创建过程需要加锁支持延迟加载不支持高并发
不加锁
只是对懒汉式创建的一个理解在GetInstnce方法里判断singleton是否为空为空的话就去创建一个实例否则直接返回该实例。
存在线程安全问题高并发的时候会创建多个对象不推荐使用。
package singleton// 单例模式 懒汉式实现 不加锁
type Singleton struct{}var singleton *Singletonfunc GetInstance() *Singleton {if singleton nil {singleton Singleton{}}return singleton
}
给方法加锁
对GetInstance整个方法进行加锁确保并发安全但是每一个对象创建的时候都需要进行加锁解锁效率低
package singletonimport sync// 单例模式 懒汉式实现 方法锁
type Singleton struct{}var singleton *Singleton
var mu sync.Mutexfunc GetInstance() *Singleton {mu.Lock()defer mu.Unlock()if singleton nil {singleton Singleton{}}return singleton
}双重检测
在懒汉式的基础上将方法的锁改为类级别的锁相对于懒汉式的粒度更小不用每次都去获取锁
借助sync.Once确保只创建一次
package singletonimport sync// 单例模式 懒汉式实现 双重检测
type LazySingleton struct{}var lazySingleton *LazySingleton
var once sync.Once{}func GetLazyInstance() *LazySingleton {if lazySingleton nil {once.Do(func() {lazySingleton LazySingleton{}})}return lazySingleton
}
静态内部类
java的静态内部类线程安全延迟加载
枚举
java的枚举特性
测试性能
测试饿汉式的init实现方法和懒汉式的sync.Once实现方法
package singletonimport testingfunc BenchmarkGetInstanceParallel(b *testing.B) {b.RunParallel(func(pb *testing.PB) {for pb.Next() {if GetInstance() ! GetInstance() {b.Errorf(test fail)}}})
}func BenchmarkGetLazyInstanceParallel(b *testing.B) {b.RunParallel(func(pb *testing.PB) {for pb.Next() {if GetLazyInstance() ! GetLazyInstance() {b.Errorf(test fail)}}})
}
在对应的目录下执行
go test -benchParallel$ -benchmem .可以看出饿汉式的性能更好一点
参考链接 图解设计模式 Go设计模式 Golang单例模式