(25)C#设计模式——单例模式

什么是单例模式?

从“单例”的字面意思上理解为:一个类只有一个实例。所以单例模式也就是保证一个类只有一个实例的一种实现方法。官方给出的定义:确保一个类只有一个实例,并提供一个全局访问点。

单例模式的实现思路

单例模式的实现代码很简单,也很容易看懂,但每次使用都会想为什们前人会这样实现单例模式呢?他们如何思考的呢?

我们从单例模式的概念入手,可以把概念分为两部分:(1)确保一个类只有一个实例。(2)提供一个访问它的全局访问点。通过一个对话情景来分析下思路:


                   新手:怎样确保一个类只有一个实例?

                   高手:你创建类的实例会想到用什么方式?

                   新手:用new关键字吧,只要new下就创建的类的一个个实例了,之后就可以使用该类的一些属性和实例方法了

                   高手:那你想过为什么可以使用new关键字来创建类的实例吗?

                   新手:我想想.....哦,想起来了。如果类定义了私有的构造函数就不能在外界通过new创建实例了。(在编写一个类是,很多时候我们没有自己编写构造函数,此时编译器会帮我们生成一个共有的无参的构造函数)

                   高手:嗯。就是这样。

                   新手:那我要在哪里创建类的实例?

                   高手:你笨啊,当然是在类里面创建了,(注:这样定义私有构造函数就是上面的一个思考过程。要创建实例,就需要一个变量来保存该实例,所有就有了私有变量的声明。但是现实中是定义静态私有变量,为什么?因为每个线程都有自己的线程栈,定义为静态主要是为了在多线程确保类只有一个实例)

                   新手:明白了。但是还有一个疑问:现在类实例创建在类的内部,那外界如何获得该类的一个实例来使用它?

                   高手:你可以定义一个共有方法或者属性来把该类的实例公开出去。(这样就有了共有方法的定义了,该方法就是提供方法访问类的全局访问点)

下面贴出单例模式的实现代码:

public class Singleton
{
    //定义一个私有变量来保存类的实例
    private static Singleton uniqueInstance;
    //定义私有构造函数
    private Singleton()
    {
    }
    //定义公有方法提供一个全局的访问点,同时也可以定义公有属性来提供全局访问点
    public static Singleton GetInstance()
    {
        if(uniqueInstance == null)
        {
            uniqueInstance = new Singleto();
        }
        return uniqueInstace;
    }

}

上面单例模式的实现在单线程下确实是完美的,然而在多线程的情况下会得到多个Singleton实例,因为在两个线程同时运行GetInstance方法时,此时两个线程判断(uniqueInstance == null)这个条件时都返回为真,此时两个线程就都会创建Singleton实例,这样就违背了单例模式的初衷了。既然上面的实现会运行多个线程执行,那么对于多线的解决方案就是让GetInstance方法在同一时间只运行一个线程运行就行了,也就是线程同步的问题了(后续会讲)。

public class Singleton
{
    //定义一个私有变量来保存类的实例
    private static Singleton uniqueInstance;
    //定义私有构造函数
    private Singleton()
    {
    }
    //定义公有方法提供一个全局的访问点,同时也可以定义公有属性来提供全局访问点
    public static Singleton GetInstance()
    {
        //当第一个线程运行到这里时,此时会对locker对象“加锁”
        //当第二个线程运行该方法时,首先检测到locker对象为“加锁”状态,该线程就会挂起,等待第一个线程解锁

        //lock语句运行完毕之后,会为该对象“解锁”
        //双重锁定只需要一句判断就可以了
        if(uniqueInstance == null)
        {
            lock(locker)
            {
                if(uniqueInstance == null)
                {
                    uniqueInstance = new Singleto();
                }
            }  
        }
        return uniqueInstance;
    }

}

猜你喜欢

转载自blog.csdn.net/qq_39003429/article/details/82049998
今日推荐