首页 > 编程语言 >c# 单例模式的实现

c# 单例模式的实现

时间:2022-12-17 22:44:06浏览次数:64  
标签:Singleton c# 模式 instance 实例 static 单例 new

原文链接:https://www.jb51.net/article/205472.htm

记一下学习单例模式的笔记:

  单例就是要保证该类仅有一个实例。实现完全封闭的单例(外部不能new)其实就要两点要求:

  • 全局访问:需要一个该类型的全局静态变量,每次获取实例时都要判断它是否null,不存在new,存在通过一个方法直接返回该值获取实例来保证对象唯一;
  • 实例化控制:new实例不能外部new、造成实例不唯一,需要一个私有构造器禁用共有构造器。

  根据new实例的时机,分为饿汉式和懒汉式:

一、 饿汉式单例:静态变量初始化时new

特点:加载时new,一开始全局就存在该唯一实例,每次用到只要获取就行,提前占用系统资源但不存在线程安全问题。代码如下:

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

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

二、 懒汉式单例:需要该实例的时候再new

特点:真正需要用到的时候才实例化,不提前占用资源但多个线程同时用到该实例时,会存在判断静态变量都为null都去new而产生多个实例的情况。有线程安全问题,但可以用双重锁定解决。

  单线程懒汉单例代码如下:

public class Singleton
  {
    private static Singleton instance = null;
    private Singleton() { }

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

多线程懒汉单例代码如下:

public class Singleton
  {
    private static Singleton instance = null;
    private static readonly object obj = new object();
    private Singleton() { }

    public static Singleton GetInstance()
    {
      //双重锁定
      if (instance == null)//只有为null需要实例化处理时才进行加锁,提高性能避免不必要的等待
      {
        lock (obj)
        {
          if (instance == null)//避免其他线程等待锁释放期间有线程已经实例化,从而造成多个实例
            instance = new Singleton();
        }
      }
      return instance;
    }
  }

三、 注册式单例

介绍一个有意思的单例-泛型注册式,是对单例的扩展,主要了解它的设计思想。

  其实每个类单例模式实现代码都是差不多的:

  1. 相同结构和成员(字段、属性、行为等):是否可以考虑进行抽象提取一个公共的调用接口?
  2. 成员类型或输入输出具体类型不是固定的:是否可以考虑设计一个适用于不同类型的通用处理方式而不都是Object?这个适用不同类型通用解决就要用到泛型。

  实现代码如下(例子使用饿汉式,当然也可以用懒汉式):

public abstract class Singleton<T> where T:class,new()
  {
    private static readonly T instance = new T();
    protected Singleton() { }

    public static T GetSingleton()//获取单例
    {
      return instance;
    }
  }
  public class Person : Singleton<Person> { }

可以看到这种单例通过继承的方式,既可以new实例也可以获取单例实例。如果要实现上面的完全封闭(禁用外部new),也可以完全在Person类中写个私有构造器在Singleton<T>类中实例的获取new T()改为反射调用私有构造器的方式实现,总感觉怪怪的。

  下面是主程序调用该单例方法:

static void Main(string[] args)
    {
      Person p1 = Person.GetSingleton();
      Person p2 = Singleton<Person>.GetSingleton();

      if (object.ReferenceEquals(p1, p2))
      {
        Console.WriteLine("两个对象是同一实例");
      }
      Console.ReadKey();
    }

输出结果:

 

标签:Singleton,c#,模式,instance,实例,static,单例,new
From: https://www.cnblogs.com/zhu4c4/p/16989762.html

相关文章

  • Eclipse开发配置
    1.编码配置有些导入Eclipse项目之后,会出现源码里面中文乱码问题,这时候需要我们修改一下Eclipse的编码设置。1.1输出中文乱码问题点击Windows→General→Workspace......
  • Oracle-统计信息收集-TABLE
    在Oracle数据库,执行sql语句的时候,会根据统计信息选择最优执行计划,当执行性能比自己想象的慢时,就有可能是统计信息不是最新导致。表的统计信息主要包含表的总行数(num_rows)、......
  • 浅析C语言预处理
    计算机操作系统属于计算机基础,了解C语言从源文件到可执行文件的被处理过程,有助于认识操作系统,帮助我们理解C语言的某些程序现象。第一部分程序的翻译环境和执行环境翻译环境......
  • css2
    用了次html写笔记很让我emo我还是用回md吧有出错的「地方」,我会即使改正的emmetCSS的复合选择器CSS的元素显示模式CSS的背景1.Emmet语法简介Emmet插......
  • C++学习---cstdio的源码学习分析07-刷新文件流函数fflush
    cstdio中的文件访问函数stdio.h中定义了一系列文件访问函数(fopen,fclose,fflush,freopen,setbuf,setvbuf),接下来我们一起来分析一下fflush对应的源码实现。fopen:打开文件fclose:......
  • Oracle-统计信息收集-INDEX
    索引的统计信息主要包含索引blevel(索引高度-1)、叶子块的个数(leaf_blocks)以及集群因子(clustering_factor)。我们可以通过数据字典DBA_INDEXES查看索引的统计信息。创建索引......
  • MySQL Workbench的安装
    1.下载MySQLWorkbench下载MySQLWorkbench2.安装步骤-下载MySQLWorkbench的msi包-安装过程-更改安装路径-安装成功-登录数据库-进入数据库-......
  • 题解 CF1762E【Tree Sum】
    problem根据prufer引理,有标号的无根树的种类是\(n^{n-2}\)。对于一棵n个节点的带权无根树,边权总是+1或者-1。那么总共有\(n^{n-2}*2^{n-1}\)种树。其......
  • Arduino UNO使用esp8266以TCP方式连接onenet云
    1.在onenet云平台上先创建一个TCP类型的产品 <1>打开onenet云平台,选择旧版,点击控制台,选择多协议接入(没有注册的先注册)图1-1 <2>多协议接入中选择TCP透传 图1-2......
  • 大数处理-BigInteger 和 BigDecimal 类
    1.BigInteger和BigDecimal类应用场景BigInteger适合保存比较大的整型;BigDecimal适合保存精度更高的浮点型(小数);2.BigInteger和BigDecimal常见方法publi......