.Net设计模式_单列模式

2018-06-18 05:16:48来源:未知 阅读 ()

新老客户大回馈,云服务器低至5折

理解

博友的经典说法:很多人排队去厕所蹲坑一样,每一次只能让一个人去蹲坑,这是一种通俗的理解。

理论上的理解则为,我们需要写一个类,这个类的作用就是控制,从而保证在整个应用程序的生命周期中,在任何时刻,被调用的类只有一个实例。

设计者需要为使用者提供一个该模式的一个全局访问点。

 

代码理解

入门实例:

public class Singleton
 {
        private static Singleton instance;

        private Singleton()
        {

        }

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

对代码的理解:
1、保证在整个应用程序的生命周期中,在任何时刻,被调用的类只有一个实例。如何做到?

     第一点就是把类的构造函数私有化,这样,调用者就不能通过New,来生成实例。

2、private static Singleton instance,该变量的作用,就是返回给调用者的类实例对象。

     因为该实例在生命周期中,是唯一的,所以定义一个私有的、静态的、全局变量instance来保存该类的唯一实例。

3、上述的变量实例是一个私有的,而且我们把类的构造函数私有化了,那么我们就必须写一个方法来返回类的实例对象。

     提供一个全局函数访问,获得instance实例,并且在该函数编写控制实例数目的逻辑,即通过if语句判断instance是否已被实例化,

     如果没有则可以同new()创建一个实例;否则,直接向客户返回一个实例。

注意:这种方式的实现对于线程来说并不是安全的,因为在多线程的环境下有可能得到Singleton类的多个实例。如果同时有两个线程去判断(instance == null),并且得到的结果为真,这时两个线程都会创建类Singleton的实例,这样就违背了Singleton模式的原则。实际上在上述代码中,有可能在计算出表达式的值之前,对象实例已经被创建,但是内存模型并不能保证对象实例在第二个线程创建之前被发现。(这段话出之:http://www.cnblogs.com/Terrylee/archive/2005/12/09/293509.html)

多线程实例:

public class Singleton
{
    private static Singleton instance;
    private static object _lock = new object();

    private Singleton()
    {

    }

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

对代码的理解:
1、这段代码与《入门实例》的区别在与,

  # 多了一个变量private static object _lock = new object()

      # 在公开方法中对该变量加了锁

   # 在加锁后,对实例做了判空处理

2、_lock变量申明为私有的、静态的、全局变量的目的就是保证生命周期中的唯一,这样对它加锁后,线程模式下,就会出现加锁等待。

3、内层的if语句块中,对实例做了一个空判断,解决了线程并发问题,同时避免在每个 Instance 属性方法的调用中都出现独占锁定。

     它还允许您将实例化延迟到第一次访问对象时发生。这种方式仍然有很多缺点:无法实现延迟初始化。

注意:这种模式是我们常用的

运行时实例:

public sealed class Singleton
{
    static readonly Singleton instance = new Singleton();

    static Singleton()
    {
    }

    private Singleton()
    {
    }

    public static Singleton Instance
    {
        get
        {
            return instance;
        }
    }
}

 对代码的理解:

1、类的申明为sealed,阻止发生派生,而派生可能会增加实例

2、实例变量申明为readonly,这个是关键点(readonly为运行时常量)。

     第一次运行,会在全局的静态存储区域中初始化,因为是readonly的,所以就只会初始化一次,以后不会在变。

     这中方案的缺点是:对实例化机制的控制权较少,就是说你没有调用实例,但实例对象已经生成。(我觉得无所谓)

3、我觉得不需要第二构造函数,不知道为啥,李大牛(http://www.cnblogs.com/Terrylee/archive/2005/12/09/293509.html)的设计模式中添加了第二个构造函数。

   期待大家解惑(不写,默认就是啊)。

     看完汤姆叔的http://www.cnblogs.com/TomXu/archive/2011/12/19/2291448.html博客(惭愧),解惑。

延迟初始化实例:

public sealed class Singleton
{
    private Singleton()
    {
    }

    public static Singleton Instance
    {
        get
        {
            return Nested.instance;
        }
    }

    private class Nested
    {
        static Nested()
        {
        }

        internal static readonly Singleton instance = new Singleton();
    }
}

 对代码的理解:

1、这段代码与《运行时实例》的区别就是,只有在你调用时,才会在生成实例到全局的静态存储区域中。

应用的场景:

我使用Microsoft.Practices.Unity容器在config中配置了依赖注入的实现,那么我需要去读取这些配置,

<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
    <alias alias="" type="" />
    <alias alias="" type="" />
    <container name="XXXAdapter">
    </container>
    <container name="YYYAdapter">
    </container>
</unity>
internal sealed class InitContainer
{
    private static IUnityContainer container;
    private static readonly object _lock = new object();

    private InitContainer()
    {
    }

    public static IUnityContainer GetInstance()
    {
        if (container == null)
        {
            lock (_lock)
            {
                if (container == null)
                {
                    container = new UnityContainer();
                    //获取指定名称的配置节
                    UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
                    container.LoadConfiguration(section, "");
                    container.LoadConfiguration(section, "");
                }
            }
        }

        return container;
    }
}

 这样就保证只读取一次的配置信息

 

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:代码重构——基础篇

下一篇:C#中Messagebox.Show()常用参数用法详解