c# 单例模式的实现
作者:JN-SHao 发布时间:2023-06-12 01:16:44
记一下学习单例模式的笔记:
单例就是要保证该类仅有一个实例。实现完全封闭的单例(外部不能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;
}
}
三、 注册式单例
介绍一个有意思的单例-泛型注册式,是对单例的扩展,主要了解它的设计思想。
其实每个类单例模式实现代码都是差不多的:
相同结构和成员(字段、属性、行为等):是否可以考虑进行抽象提取一个公共的调用接口?
成员类型或输入输出具体类型不是固定的:是否可以考虑设计一个适用于不同类型的通用处理方式而不都是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();
}
输出结果:
来源:https://www.cnblogs.com/jn-shao/p/14318813.html


猜你喜欢
- 今天一直在绞尽脑汁的寻找解决两个字符之间的内容如何输出的问题,刚开始就使用了万能的正则表达式;但是不知哪里的原因自己的数据一直出不来,觉得应
- 首先定义两个示例类ClassA,ClassB,用于后续的示例演示package cn.lzrabbit;public class Class
- 一、概述 在C和C++语言中都有assert关键,表示断言。在Java中,同样也有assert关键字,表示断言,用法和含义都差不多
- 配置文件<?xml version="1.0" encoding="utf-8" ?>&
- 前言早在2011年它作为安卓兼容库发布,在75%的应用中使用过,是最广泛使用的安卓库。它事实上不是一个单一的文件,而是一个集合,其中可以大致
- eureka获取服务ip和端口号进行Http调用我告诉你们为啥我要先从eureka首先获取 goods的服务ip, 在用ip的方式使用htt
- java文字识别程序的关键是寻找一个可以调用的OCR引擎。tesseract-ocr就是一个这样的OCR引擎,在1985年到1995年由HP
- @Valid注解可以实现数据的验证,你可以定义实体,在实体的属性上添加校验规则,而在API接收数据时添加@valid关键字,这时你的实体将会
- 日期类计算器的模拟实现::1.获取某年某月的天数int GetMonthDay(int year, int month){static in
- @Api注解不展示controller内容一开始我是这么写的@Api(value = "企业controller")然后
- 引言java中的Math.random()是一个在[0,1)范围等概率返回double数值类型的算法,基于此函数,我们来延申一些随机概率算法
- 之前百度,google了很多,发现并没有介绍mongodb生产环境如何配置的文章, 当时想参考下都不行, 所以写篇文章,大家可以一块讨论下.
- 今天给大家介绍一个仿微信的图片选择器:ImageSelector。ImageSelector支持图片的单选、限数量的多选和不限数量的多选。支
- 这次记录的是实现Android图片用手拖拉的功能,,供大家参考,具体内容如下编译环境:eclipseAndroid版本4.0创建工程过程略实
- 在没讲.net如何随机生成汉字之前先给大家讲下汉字编码组成及原理。1、汉字编码原理到底怎么办到随机生成汉字的呢?汉字从哪里来的呢?是不是有个
- 本文实例为大家分享了Android实现界面跳转的具体代码,供大家参考,具体内容如下布局<?xml version="1.0&
- 题目:求100之内的素数方法一:package airthmatic;public class demo8 { /** * 素数是指因数只有
- 一、reservedcodecachesize参数介绍该参数是JvM虚拟机调优中调整内存大小的一个设置参数,值得大小设置直接影响到Code
- 本文章从头开始介绍Spring集成Redis的示例。Eclipse工程结构如下图为我的示例工程的结构图,采用Maven构建。其中需要集成Sp
- 概述非对称加密算法与对称加密算法的主要差别在于非对称加密算法用于加密和解密的密钥不相同,非对称加密算法密钥分为公钥和私钥,公钥加密只能用私钥