(一)单例设计描述

只要了解过设计模式的同学都会知道:单例设计模式,大家都知道单例设计模式是一种创建行的设计模式。既然是创建型,那么先来讲讲,对象的创建的过程吧。

--静态成员:静态成员在程序加载的时候,就会加载进内存。

--实例成员:只有new的时候才有实例成员。1、为实例的数据字段分配内存,然后初始化对象的附加字段(类型指针和同步索引块),最后调用类型的实例构造器来设置对象的初始化状态。

单例模式:一般用在一个类的创建对象很消耗资源,消耗时间,并且系统要保证只有一个对象的时候。一句话,对象的创建并不是很耗时间,不要刻意去套用单例模式,单例模式必须是在单例的时候,才单例。

(二) 单例模式的演变

下面我们来模拟实际情况

 public class Singleton {/// <summary>/// 对象会持有资源/// </summary>private List<string> _connList=new List<string>(){"测试数据库连接","测试数据库连接2","测试数据库连接3","测试数据库连接4"};public Singleton(){long lResult = 0;for (int i = 0; i < 100000; i++){lResult += i;}Thread.Sleep(1000);Console.WriteLine("{0}被构造一次",this.GetType().Name);}public void Show(){Console.WriteLine("调用了Show");}}

这个类的创建需要耗费很多资源,里面有个Show方法。

那么接下来,实际中,我们可能有十个地方要用到这个类里面的Show方法,我们的做法是这样的

  //那么接下来,我们这里要调用十次Show方法for (var i = 0; i < 10; i++) {var singletonObj = new Singleton();singletonObj.Show();}

这里每次调用一次,都需要耗费很多资源和时间,这里可能有些同学就会说,那我把这个singletonObj=new Singleton()提取出来,放到最外面来。

那行,按照我们需要,我们把var singletonObj=new Singletone()放到外面,如下所示

貌似这样就解决了我们的问题,但是各位你们想一想,我们一个系统是有多个人开发的,A这里这样做,B可能不知道这里有这个声明,那他可能就还是一样去New Singleton,还是导致我们系统中,存在大量这个对象。

我们应该要如何解决这个问题呢? 如何保证这个对象在整个系统只被创建一次呢?

单例模式--单线程

从上面的问题,我们也可以看出因为谁都可以在New Singleton,所以导致了这个问题。那按照这个想法,那我们就想啦,那就把构造函数私有化呗,私有化完了之后,我们应该还要提供一个方法或者啥的,给外面调用(也只能是静态的成员),构造函数私有化了,外面是不可以New了的

那就按照,刚刚的说法,我们来进行一次改进

public class Singleton {/// <summary>/// 对象会持有资源/// </summary>private List<string> _connList=new List<string>(){"测试数据库连接","测试数据库连接2","测试数据库连接3","测试数据库连接4"};private Singleton(){long lResult = 0;for (int i = 0; i < 100000; i++){lResult += i;}Thread.Sleep(1000);Console.WriteLine("{0}被构造一次",this.GetType().Name);}public static Singleton CreateInstance(){return new Singleton();}public void Show(){Console.WriteLine("调用了Show");}}

按照我们上面这个写法,把构造函数私有化了,然后在静态方法里面New Singletone();

调用结果如下:

 for (var i = 0; i < 10; i++) {var singletonObj = Singleton.CreateInstance();singletonObj.Show();}  //写进里面去了,是为了模拟有十个不同的开发,再调用

那结果,还是没有达到我们想要的,那现在问题就是,对象没有重用,因为我们每次new,导致了对象没有做到重用,那就让对象进行重用呗。最简单的方法,就是给一个静态的字段(为啥静态呢,因为我们那边方法是静态的),然后做一个判断,如果对象为空,那么我们就创建,如果不为空,就不用创建了,如下所示。

我们在原来的基础上,做了如上图的改进。结果如下,

我们想要的结果实现了,多次调用的时候,做了重用对象,只构造了一次。本来想着单例模式就这样结束了(单线程是没有问题,并且这种实现是一种懒汉式,懒汉式:当你需要用这个类的时候,才会去实例化)。

编程世界里面,我们总是要考虑一下,多线程的情况。

单例模式--多线程

这个是用Task.Run()开启了也给多线程的异步调用

 for (var i = 0; i < 10; i++){Task.Run(()=>{var singletonObj = Singleton.CreateInstance();singletonObj.Show();});      }Thread.Sleep(5000);

通过上面的结果,我们可以看出,我们的之前的做法,在多线程环境还是会调用多次。

有些同学就会说用lock锁啦,行,我们就给他加上一把锁。

public class Singleton {/// <summary>/// 对象会持有资源/// </summary>private List<string> _connList=new List<string>(){"测试数据库连接","测试数据库连接2","测试数据库连接3","测试数据库连接4"};private static Singleton singletonObj = null;private static readonly object singleTonObjLock = new object();  //加锁,之后这里为啥要用readonly,大家可以找private Singleton(){long lResult = 0;for (int i = 0; i < 100000; i++){lResult += i;}Thread.Sleep(1000);Console.WriteLine("{0}被构造一次",this.GetType().Name);Console.WriteLine($"线程{Thread.CurrentThread.ManagedThreadId}调用一次");}public static Singleton CreateInstance(){lock (singleTonObjLock) //很多同学都说用lock this,this肯定是不行的,因为lock是lock引用的,如果这个this的引用改变了...
            {if (singletonObj == null){singletonObj = new Singleton();}}return singletonObj;}public void Show(){Console.WriteLine("调用了Show");}}

看我们给他加完锁的时候效果。

嗯,实现了我们想要的效果了,说明我们加锁是有效果的。到了这个时候,大家可能觉得一个单例模式应该就快结束了,那么我们再来看看这种情况。

单例模式--多线程(双if+lock)

通过上面的介绍,我们理解了单例模式的演变过程,也对单例模式,多线程有了更加深刻的印象。

(三)单例模式其他实现

就像我们一开始说的那样,单例模式,其实一个进程内,在多线程环境下,如何保证只有一个对象,这就是单例。也可以从这个定义看出,我们可以通过静态的构造函数来实现一个单例模式。

静态构造函数,是由CLR保证的,有且只会加载一次。

其他很多方法实现,都是利用static关键字的背后原因,在第一次使用类型之前被调用,且只会被调用一次。

(四)懒汉式,饿汉式

懒汉,就是说这个人很懒,需要用的时候,才构建。双if+lock这种就属于懒汉式。懒汉式,利用了延迟加载加载的思想。

饿汉:就是调用我这个类型,就会帮你创建好;管你用不用,我都会帮你创建;就是饿了吗,我后面介绍的利用static关键字的就是属于饿汉式;饿汉式:管你之前有没有(内存中),都会帮你new一个新的实例。

(五)单例模式的使用场景

单例:必须单例才单例,反正没必要。单例模式实现都有性能,损失,静态方法。

单例:会把对象常驻内存,静态的。

单例的使用,多个人操作可能会对你影响,因为都是对同一份引用进行修改。

一般用在数据库连接,打印机,远程服务调用,等等这些大对象身上。

   //单例模式的应用场景补充:读取配置文件信息,读取配置文件不应该一直new一个类,应该是单例的。

   public class ConfigV1{private static object _lockObj = new object();private static ConfigV1 _instance;private static Dictionary<string,string> _configItems =new Dictionary<string, string>();private ConfigV1(){Init();Console.WriteLine($"{this.GetType().Name}被构造一次");}public static  ConfigV1 GetInstance(){if (_instance == null){lock (_lockObj){if (_instance == null){_instance=new ConfigV1();}}}return _instance;}public string  this[string item]{get{return _configItems[item];}}private  void Init(){var config=ConfigurationManager.AppSettings.AllKeys;foreach(var key in config){_configItems.Add(key,ConfigurationManager.AppSettings[key]);}}}

github:https://github.com/gdoujkzz/DesignPattern.git

  谢谢你阅读我的博客,如果有收获,请点一个赞(推荐)

转载于:https://www.cnblogs.com/gdouzz/p/8319485.html

小看--单例设计模式相关推荐

  1. python基础知识整理 第七节:单例设计模式、异常、模块、包、制作模块、文件

    1.单例设计模式 单例设计模式就是为对象在内存中分配空间的时候,永远只会返回一个唯一的固定的内存空间.这样就能保证在内存中这个类的对象只有唯一的一份,这个就叫做单例.(为对象分配空间使用的是内置方法_ ...

  2. 单例设计模式详解。。。。。。。。。。。

    public class Demo01 { public static void main(String[] args) { // TODO Auto-generated method stub /* ...

  3. 对于java程序语言的单例设计模式讲解

    1.设计模式:解决某一类问题最行之有效的方法.(java中有23种通用设计模式) 单例设计模式:解决一个类在内存中只存在一个对象. 2.单例设计模式有两种方式: 1)饿汉式 先初始化对象.当类一进内存 ...

  4. java软件设计模式只单例设计模式

    概述 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. 毫无疑问,设计 ...

  5. AJPFX关于单例设计模式

    单例设计模式优势:保证一个类在内存中的对象唯一性. 比如:多程序读取一个配置文件时,建议配置文件封装成对象.会方便操作其中数据,又要保证多个程序读到的是同一个配置文件对象,就需要该配置文件对象在内存中 ...

  6. java饿汉式有啥作用,Java面试 - 什么是单例设计模式,为什么要使用单例设计模式,如何实现单例设计模式(饿汉式和懒汉式)?...

    什么是单例设计模式? 单例设计模式就是一种控制实例化对象个数的设计模式. 为什么要使用单例设计模式? 使用单例设计模式可以节省内存空间,提高性能.因为很多情况下,有些类是不需要重复产生对象的.如果重复 ...

  7. 单例设计模式singleton

    简单引入 单例设计模式作为最简单,最常用的设计模式.一般是这两中写法,这两种写法教科书所谓的标准写法,但是实际上存在不少问题.后面介绍标准写法,以规避这些问题. 1.懒汉式: /*** 问题在于,当多 ...

  8. 面向对象——单例设计模式

    单例设计模式: 解决一个类在内存只存在的一个对象 //getInstance()    返回对象 饿汉式:先初始化对象 class Si{ private static Si s=new SI(); ...

  9. Python单例设计模式

    (1)为什么使用设计模式? 使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. (2)单例设计模式概念 让类创建的对象只有唯一的一个实例,即每次执行  类名() 返回的对象,内存地 ...

最新文章

  1. C++中的赋值操作符重载
  2. MySQL 如何实现 Oracle 的 row_number() over() 分组排序功能
  3. java knn文本分类算法_使用KNN算法的文本分类.PDF
  4. SpringBoot整合Shiro(Java安全框架)案例(含源码)
  5. Zabbix分布式监控系统使用总结
  6. NASA-TLX (Task Load Index)量表学习总结
  7. Tomcat安装及idea配置教程
  8. 2-4 实变函数之可测函数
  9. 使用百度地图API进行Android地图应用开发(Eclipse)
  10. python随机森林库_随机森林算法入门(python)
  11. 保险行业的“偿二代”
  12. 常用计算机系统包括,常用的保护计算机系统的方法有()。
  13. 计算机应用计术,计算机应用技术.ppt
  14. 浮点数比大小(C语言版)
  15. linux与windows双系统windows无法连网问题的解决
  16. [日推荐]『拉了吗』出门必备
  17. 中台技术爆发,这个软件定义中台专利指出了数字化转型路径
  18. matlab生成一个数值一样的向量
  19. [突发奇想的JS小案例] 2 重力模拟
  20. 结合 ArcGIS 对 CAD 地图入库处理

热门文章

  1. 打开 谷歌浏览器exe_专治各种网银不服:两步开启微软Edge浏览器IE兼容模式
  2. 【技术解决方案】开发工具源码安装包大全
  3. C语言结构体使用与指针的理解
  4. 英文期刊催稿信模板_手把手教你写投稿信,另附查尔斯沃思高质量模板
  5. python删除字符串中指定_python删除字符串中指定字符
  6. openfire消息通知推送_微信小游戏内测「订阅消息」能力,这是召回用户的「大杀器」吗?...
  7. docker $PWD路径_Docker安装Jenkins+Shell脚本自动化部署项目
  8. 事件触发控制_SystemVerilog线程控制与通信
  9. mysql过滤器_MYSQL复制过滤器
  10. PCM设备在雷达通信系统应用