.Net设计模式之单例模式(Singleton)

 更新时间:2022年05月09日 08:34:06   作者:springsnow  
这篇文章介绍了.Net设计模式之单例模式(Singleton),文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

一、动机(Motivation)

在软件系统中,经常有这样一些特殊的类,必须保证它们在系统中只存在一个实例,才能确保它们的逻辑正确性、以及良好的效率。

如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例?

这应该是类设计者的责任,而不是使用者的责任。

二、意图(Intent)

保证一个类仅有一个实例,并提供一个该实例的全局访问点

三、结构(Structure)

image

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

四、单例模式的代码实现

1、单线程Singleton模式的实现

public sealed class Singleton
{
    private static Singleton uniqueInstance;// 定义一个静态变量来保存类的实例

    private Singleton() // 定义私有构造函数,使外界不能创建该类实例
    {
    }

    /// 

    /// 定义公有方法提供一个全局访问点,同时你也可以定义公有属性来提供全局访问点
    /// 
    /// 
    public static Singleton GetInstance()
    {
        if (uniqueInstance == null)// 如果类的实例不存在则创建,否则直接返回
        {
            uniqueInstance = new Singleton();
        }
        return uniqueInstance;
    }
}

私有的实例构造器是为了屏蔽默认产生的构造器,让类的使用者无法调用构造器。

单线程Singleton模式的几个要点

Singleton模式中的实例构造器可以设置为protected以允许子类派生。

Singleton模式一般不要支持ICloneable接口,因为这可能会导致多个对象实例,与Singleton模式的初衷违背。

Singleton模式一般不要支持序列化,因为这也有可能导致多个对象实例,同样与Singleton模式的初衷违背。

Singleton模式只考虑到了对象创建的管理,没有考虑对象销毁的管理。就支持垃圾回收平台和对象的开销来讲,我们一般没有必要对其销毁进行特殊的管理。

不能应对多线程环境:在多线程环境下,使用Singleton模式仍然有可能得到Singleton类的多个实例对象。

2、双多线程重锁定(Double Check)Singleton模式的实现

public sealed class Singleton
{
    private static volatile Singleton uniqueInstance;// volatile关键字知识此成员变量能被多个线程访问。
    
    private static readonly object locker = new object();// 定义一个标识确保线程同步

    private Singleton()// 定义私有构造函数,使外界不能创建该类实例
    {
    }

    public static Singleton GetInstance()
    {
        if (uniqueInstance == null)//先判断不存在再枷锁
        {
            lock (locker)
            {
                if (uniqueInstance == null)// 如果类的实例不存在则创建,否则直接返回
                {
                    uniqueInstance = new Singleton();
                }
            }
        }
        return uniqueInstance;
    }
}

volatile修饰符:编译器在编译代码的时候会对代码的顺序进行微调,用volatile修饰保证了严格意义的顺序。一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。

3、使用C#语言的“静态初始化”特性来实现单例的Singleton模式。(.Net中实现Singleton的首选方法)

内联初始化(生成的同时进行初始化):

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

    public static Singleton GetInstance()
    {
        return Singleton.instance;
    }

    private Singleton()//私有构造函数,防止外界调用
    {
       //...
     }
}

它等同于:

public sealed class Singleton
{
    public static readonly Singleton instance;

    //静态构造函数,初始化静态变量。CLR只执行一次
    static Singleton()
    {
        instance = new Singleton();
    }

    public static Singleton GetInstance()
    {
        return Singleton.instance;
    }

    private Singleton()//私有构造函数,防止外界调用
    {
       //...
    }
}

另一种优雅写法是要用到.net 4.0里Lazy

public sealed class Singleton
{
    private static readonly Lazy lazy =
        new Lazy(() => new Singleton());

    public static Singleton Instance => lazy.Value;

    private Singleton()
    {
    }
}

只要想访问静态字段,必定已经在之前执行了静态构造器。这样也能够精确地保证使用的时候一定能拿到实例,如果不使用也不会实例化对象,也就是延时加载的功能。他同样能够支持多线程环境,因为只可能有一个线程执行静态构造器,不可能有多个线程去执行静态构造器,感觉就是程序已经自动为我们加锁了。它的一点弊端就是它不支持参数化的实例化方法。

在.NET里静态构造器只能声明一个,而且必须是无参数的,私有的。因此这种方式只适用于无参数的构造函数。

五、.NET框架中的Singleton应用

image

t1==t2 这说明,GetType方法获得的Type实例都是单例。

HttpContext.Current也是如此,他们是通过Singleton的扩展方式实现的,他们的单例也并不是覆盖所有领域,只是针对某些局部领域中,是单例的,不同的领域中还是会有不同的实例。

到此这篇关于.Net设计模式之单例模式(Singleton)的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • .NET正则表达式的最佳用法

    .NET正则表达式的最佳用法

    本文详细讲解了.NET正则表达式最佳用法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-01-01
  • ASP.NET Core中的Options选项模式

    ASP.NET Core中的Options选项模式

    这篇文章介绍了ASP.NET Core中的Options选项模式,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-04-04
  • ASP.NET MVC中两个配置文件的作用详解

    ASP.NET MVC中两个配置文件的作用详解

    本文详细讲解了ASP.NET MVC中两个配置文件的作用,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-03-03
  • WPF图表LiveChart使用详解

    WPF图表LiveChart使用详解

    本文详细讲解了WPF图表LiveChart的用法,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-01-01
  • ABP基础架构深入探索

    ABP基础架构深入探索

    这篇文章主要介绍了ABP基础架构深入探索,为了了解应用程序是如何配置和初始化,本文将探讨ASP.NET Core和ABP框架最基本的构建模块
    2022-05-05
  • WPF中Style样式及其触发器

    WPF中Style样式及其触发器

    这篇文章介绍了WPF中Style样式及其触发器,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-01-01
  • .Net行为型设计模式之访问者模式(Visitor)

    .Net行为型设计模式之访问者模式(Visitor)

    这篇文章介绍了.Net行为型设计模式之访问者模式(Visitor),文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-05-05
  • ASP.NET Core基础之Startup类

    ASP.NET Core基础之Startup类

    这篇文章介绍了ASP.NET Core基础之Startup类,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-02-02
  • C#列出局域网中可用SQL Server服务器(续)

    C#列出局域网中可用SQL Server服务器(续)

    上一篇文章展示了使用COM对象如何列出局域网中的 SQL Server服务器信息,后来还发现在.Net中有现成的类可用,而不需要使用不太熟悉的COM对象了,这样岂不是更好?下面我把代码展示给大家:
    2008-04-04
  • WPF框架Prism中模块Module用法

    WPF框架Prism中模块Module用法

    这篇文章介绍了WPF框架Prism中模块Module的用法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-02-02

最新评论