大话设计模式-单例模式

单例模式

单例模式保证一个类仅有一个实例,并提供一个访问它的全局访问点。

通常我们可以让一个全局变量使得一个对象被访问,但他不能防止你实例化多个对象。

一个最好的办法就是,让类自身负责保存他的唯一实例。

这个类可以保证没有其他实例可以被窗创建,并且他可以提供一个访问该实例的方法。


单例模式结构演示

class Singleton{
    //静态单例成员变量
    private static Singleton instance;
    //私有构造器,使其无法被外界创建实例
    private Singleton() { }
    //静态方法,获取实例,第一次获取时创建实例
    public static Singleton GetInstance(){
        if (instance == null)
            instance = new Singleton();
        return instance;
    }
}

单例模式因为单例类封装他唯一的实例,这样他可以严格地控制客户怎样访问它以及何时访问它。即对唯一实例地受控访问。


多线程时的单例

lock是确保当一个线程位于代码的临界区时,另一个线程不进入临界区。

如果其他线程试图进入锁定的代码,则他将一直等待,直到该对象被释放。

private static Singleton instance;
private static readonly object syncRoot = new object();
private Singleton() { }
public static Singleton GetInstance(){
    lock(syncRoot){
        if (instance == null)
            instance = new Singleton();
    }
    return instance;
}

之所以再使用一个syncRoot作为lock地参数,是一位加锁时不知道instance实例有没有被创建。

但是这样每次调用GetInstance方法时都要lock。

双重锁定

再加一层instance==null的判断,判断实例是否存在,不存在的情况再进行加锁处理。

public static Singleton GetInstance(){
    if (instance == null){
        lock (syncRoot){
            if (instance == null)
                instance = new Singleton();
        }
    }
    return instance;
}

之所以内部还需要再判断一次是因为,假如实例还未创建,两个线程通过了第一层。

第一个线程先进入锁内,创建了实例,如果不加判断,第二个线程就又创建一次实例。


静态初始化

C#与公共语言运行库也提供了一种静态初始化的方法,这种方法不需要显式地编写线程安全代码,即可解决多线程环境下他是不安全的问题。

public sealed class Singleton{
    private static readonly Singleton instance=new Singleton();
    private Singleton() { }
    public static Singleton GetInstance() => instance;
}

这种实现和前面的类似,也是解决了全局访问和实例化控制这两个问题,公共静态属性为访问实例提供了一个全局访问点。

不同的是,它依赖于公共语言运行库来初始化变量。由于构造器时私有的,不能在类本身以为实例化单例类,因此变量引用的是可以在系统中存在的唯一实例。

这种静态初始化的方法是在自己被加载时就将自己实例化,所以被称为饿汉式单例类

之前的单例处理模式是要在第一次被引用时才会将自己实例化,被称为懒汉式单例类

猜你喜欢

转载自www.cnblogs.com/errornull/p/10072444.html