设计模式之单例模式

一、概念

单例模式:一种常用的软件设计模式,保证系统中一个类只有一个实例,且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源

二、三个要点

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
}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值