一、概念
单例模式:一种常用的软件设计模式,保证系统中一个类只有一个实例,且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源
二、三个要点
1、单例类只能有一个实例;
2、单例类必须自己创建自己的唯一实例;
3、单例类必须为其他对象提供唯一的实例。
三、实际应用
线程池、缓存、日志对象、对话框、显卡驱动程序、管理类、代理类、资源管理器、回收站、打印机等通常设计为单例模式
四、优缺点
优点:(1)实例控制:单例模式会阻止其他对象实例化自己的单例对象的副本,从而确保所有对象都访问唯一实例;(2)灵活性:因为控制了实例化过程,所以类可以灵活更改实例化过程;
缺点:(1)开销:虽然数量很少,但如果每次对象请求引用时都要检查是否存在类的实例,将仍然需要一些开销。可以通过使用静态初始化解决此问题;(2)可能开发混淆:使用单例对象(尤其在类库中定义的对象)时,开发人员必须记住自己不能使用new关键字实例化对象。因为可能无法访问库源代码,因此应用程序开发人员可能会意外发现自己无法直接实例化此类;(3)对象生存期:不能解决删除单个对象的问题。在提供内存管理的语言中(例如基于.NET Framework的语言),只有单例类能够导致实例被取消分配,因为它包含对该实例的私有引用。在某些语言中(如 C++),其他类可以删除对象实例,但这样会导致单例类中出现悬浮引用。
五、实现方法
1、第一种形式:懒汉式(常用)
//第一次调用自己的时候实例化自己
public class Singleton {
private static Singleton instance = null;
public static synchronized Singleton getInstance(){
if(instance == null)
instance = new Singleton();
return instance;
}
private Singleton(){
//do something
}
}
2、第二种形式:双重锁形式(仍属于懒汉式,但在引入了双重检查保证线程安全)
public class Singleton{
private static Singleton instance=null;
public static Singleton getInstance(){
if(instance==null){
synchronized(Singleton.class){
if(null==instance){
instance=new Singleton();
}
}
}
return instance;
}
private Singleton(){
//do something
}
}
3、第三种形式:静态内部类(仍属于懒汉式,较上面两种即实现了线程安全,又避免了同步锁带来的性能影响)
public class Singleton{
private static Singleton(){}
private static class innerClass{
private static final Singleton instance = new Singleton();
}
public static Singleton getInstance(){
return innerClass.instance;
}
private Singleton(){
//do something
}
}
4、第四种形式:饿汉式(天生线程安全)
//对第一行static的一些解释
//java允许我们在一个类里面定义静态类。比如内部类(nested class)。
//把nested class封闭起来的类叫外部类。
//在java中,我们不能用static修饰顶级类(top level class)。
//只有内部类可以为static。
public class Singleton{
//在自己内部定义自己的一个实例,只供内部调用
private static final Singleton instance = new Singleton();
//这里提供了一个供外部访问本class的静态方法,可以直接访问
public static Singleton getInstance(){
return instance;
}
private Singleton(){
//do something
}
}
六、二者区别
饿汉就是类一旦加载,就把单例初始化完成,保证getInstance的时候单例对象的实例已经存在。所以是线程安全的;
而懒汉式只有当getInstance的时候才会去初始化这个单例。所以需要通过二、三种方法来保证线程安全
golang实现版本:
(1)懒汉式
type singleton struct{}
var ins *singleton
func GetIns() *singleton{
if ins == nil {
ins = &singleton{}
}
return ins
}
(2)饿汉式
type singleton struct{}
var ins *singleton = &singleton{}
func GetIns() *singleton{
return ins
}
(3)懒汉加锁式
type singleton struct{}
var ins *singleton
var mu sync.Mutex
func GetIns() *singleton{
mu.Lock()
defer mu.Unlock()
if ins == nil {
ins = &singleton{}
}
return ins
}
(4)双重锁
type singleton struct{}
var ins *singleton
var mu sync.Mutex
func GetIns() *singleton{
if ins == nil {
mu.Lock()
defer mu.Unlock()
if ins == nil {
ins = &singleton{}
}
}
return ins
}
(5)sync.Once实现,避免了每次加锁,提高代码效率
type singleton struct{}
var ins *singleton
var once sync.Once
func GetIns() *singleton {
once.Do(func(){
ins = &singleton{}
})
return ins
}