Singleton 单例模式简介与 C# 示例【创建型】【设计模式来了】

 〇、简介

1、什么是单例模式?

一句话解释:

  单一的类,只能自己来创建唯一的一个对象。

单例模式(Singleton Pattern)是日常开发中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有一个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象

 一个比喻:(班主任与学生)

  比如一个班级,只有一个班主任,任何一个同学要找班主任,都是找的同一个,班主任忙的时候,当然就出现排队的情况。

2、优缺点和使用场景

  • 优点:内存里只有一个实例,减少了内存的开销,也避免了对象高频创建带来的性能损耗。
  • 缺点:任务量大时,会出现排队,耗时增加。另外与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。

 使用场景举例:

  • 要求生产唯一序列号。
  • WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。
  • 创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。

一、单例模式简单实现

public class Singleton
{
    private static Singleton instance = null;
    private static object lockObject = new object();
    /// <summary>
    /// 私有化构造函数,防止外部实例化
    /// </summary>
    private Singleton() { }
    public static Singleton Instance
    {
        get
        {
            if (instance == null)
            {
                lock (lockObject) // 线程同步锁
                {
                    if (instance == null) // Lazy Initialization
                    {
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }
    /// <summary>
    /// 重置 Singleton
    /// </summary>
    public void Reset()
    {
        instance = null;
    }
}

 测试代码:

static void Main(string[] args)
{
    var instance1 = Singleton.Instance;
    var instance2 = Singleton.Instance;
    Console.WriteLine(instance1 == instance2); // 输出 true 
}

二、带参数的单例模式实现

public class SingletonParameters
{
    private static SingletonParameters instance = null;
    private static object lockObject = new object();
    private int _firstvalue, _secondvalue;
    /// <summary>
    /// 私有化构造函数,防止外部实例化
    /// </summary>
    private SingletonParameters(int first, int second)
    {
        this._firstvalue = first;
        this._secondvalue = second;
    }
    public static SingletonParameters InstanceParameters(int first, int second)
    {
        if (instance == null)
        {
            lock (lockObject) // 线程同步锁
            {
                if (instance == null) // Lazy Initialization
                {
                    instance = new SingletonParameters(first, second);
                }
            }
        }
        else
        {
            instance.FirstValue = first;
            instance.SecondValue = second;
        }
        return instance;
    }
    public int FirstValue { get { return _firstvalue; } set { _firstvalue = value; } }
    public int SecondValue { get { return _secondvalue; } set { _secondvalue = value; } }
    /// <summary>
    /// 重置 Singleton
    /// </summary>
    public void Reset()
    {
        instance = null;
    }
}

 测试代码:

var instance1 = SingletonParameters.InstanceParameters(1, 2);
Console.WriteLine($"FirstValue:{instance1.FirstValue}");
Console.WriteLine($"SecondValue:{instance1.SecondValue}");
var instance2 = SingletonParameters.InstanceParameters(3, 4);
Console.WriteLine($"FirstValue:{instance2.FirstValue}");
Console.WriteLine($"SecondValue:{instance2.SecondValue}");
Console.WriteLine($"instance1 == instance2 : {instance1 == instance2}");

 

参考:http://www.cnblogs.com/gaochundong/p/design_pattern_singleton.html

本文来自博客园,作者:橙子家,微信号:zfy1070491745,有任何疑问欢迎沟通,一起成长。

转载本文请注明原文链接:http://www.cnblogs.com/czzj/p/SJMSLL_Singleton.html

本文转载于网络 如有侵权请联系删除

相关文章

  • 性能优化之YUICompressor压缩JS、CSS

    大家好,又见面了,我是你们的朋友全栈君。性能一直是项目中比较重要的一点,尤其门户网站,对页面的响应要求是很高的,从性能角度上来讲,对于Web端的优化其中重要的一点无疑是JS、CSS文件压缩,图片的融合,尽量减小文件的大小,必免占加载时占用过多的带宽。yuicompressor无疑是一个比较好的压缩工具,是yahoo的一个开源组件,下面介绍yuicompressor压缩JS、CSS文件,及在项目中的使用yuicompressor介绍1、首先需要从https://github.com/yui/yuicompressor/downloads下载yuicompressor,我用的是目前最新的2.4.7版本,下载完成后得到一个源码包,解压后在build文件中有一个yuicompressor-2.4.7.jar,一会就用这个Jar来压缩文件2、yuicompressor需要有Java运行环境的支持,先通过Java-jar命令运行yuicmpressor-2.4.7.jar看下效果longwentaodeMacBook-Pro:Downloadslongwentao$java-jar/Users/l

  • Vue学习之事件修饰符

    大家好,又见面了,我是你们的朋友全栈君。Vue事件修饰符事件修饰符概览修饰符|说明 --------|-------------------------- .stop|阻止冒泡 .prevent|阻止默认事件 .capture|添加事件侦听器时使用事件捕获模式 .self|只当事件在该元素本身(比如不是子元素)触发时触发回调 .once|事件只触发一次复制事件修饰符具体介绍.stop.stop用来防止冒泡,我们先来看看冒泡的场景<!DOCTYPEhtml> <htmllang="en"> <head> <metacharset="UTF-8"> <metaname="viewport"content="width=device-width,initial-scale=1.0"> <metahttp-equiv="X-UA-Compatible"content="ie=edge"> <titl

  • C# 如何在项目引用x86 x64的非托管代码

    因为现在的项目使用的是AnyCpu在x86的设备使用的是x86,在x64使用的是x64,但是对于非托管代码,必须要在x64使用x64的dll,在x86使用x86的dll。在C++没有和C#一样的AnyCpu所以需要在项目运行在x86的时候加载x86的dll。本文告诉大家如何在代码引用不同的dll。使用宏最简单的方法是编译两个版本,编译多个版本可以点击配置管理器,然后创建x86和x64,然后版本添加宏,这样就可以判断宏来使用不同的dll点击活动解决方案平台,然后点击新建选择项目属性,点击生成,就可以添加不同的宏于是在后台代码可以这样写#ifx86 publicconststringDLL_FILE_NAME="SvkiqauhKvdhrureh32.dll"; #else publicconststringDLL_FILE_NAME="SvkiqauhKvdhrureh64.dll"; #endif [DllImport(DLL_FILE_NAME,EntryPoint="HfwzsnHzhpbbzbn",CallingCon

  • django-模板之URL标签(五)

    book/views.pyfromdjango.shortcutsimportrender defindex(request): returnrender(request,"index.html") defnews(request): returnrender(request,"news.html") defsports(request): returnrender(request,"sports.html")复制book/urls.pyfromdjango.urlsimportpath from.importviews urlpatterns=[ path('',views.index,name="index"), path('news/',views.news,name="news"), path('sports/',views.sports,name="sports"), ]复制base.html&

  • Python——教你画朵太阳花

    用python中的turtle函数画个太阳花,有以下几个步骤1、首先,我们在开始中找到Python语言的IDLE软件脚本2、然后出现该软件界面,如图,点击上面的Eile3、然后在栏目中点击NewFile(或着在键盘上按Ctrl+N)4、之后就会出现一个新的操作文档5、然后开始打上画太阳花所需的代码,如下:fromturtleimport*color('red','yellow')begin_fill()whileTrue:   forward(200)   left(170)   ifabs(pos())<1:       breakend_fill()done()6、然后在Edit中找到SaveAs,保存文件(或者直接按Ctrl+Shift+S)7、然后保存到你想要保存的文件夹中8、在上方栏目中找到Run,然后选择RunModule(或者直接按F5)9、这时候你就可以看到一个画面,这就是开始画太阳花了10、然后,你就可以获得一朵漂亮的太阳花了(你也可以在color中改变笔的颜色和花的颜色,在forward中改变你的花的大小,祝你玩的开心)

  • python3之鸭子类型

    鸭子类型简单的跟大家聊一聊python中的鸭子类型,通过一个例子来理解就很简单了。一句话:“当看到一只鸟走起来像鸭子,游泳起来像鸭子,叫起来也想鸭子,那么这只鸟就可以被称为鸭子。”,也就是我并不关心对象什么类型,到底是不是鸭子,只关心行为。假如定义了一个函数,传入一个类对象,我们并不需要知道这个类对象是不是我们想要的类对象,只要他有需要的方法,那么这个函数就可以执行。#1、定义两个类型,一个是鸭子类,一个是人类,他们都拥有“走”和“游泳”的方法 classDuck(): defwalk(self): print("I'maduck,Ilikewalking") defswim(self): print("I'maduck,Ilikeswimming") classPerson(): defwalk(self): print("Thisonewalklikeaduck") defswim(self): print("Thisoneswimlikeaduck")复制#鸭子类型:我们并不关心

  • [Selenium+Chrome使用总结]加载Flash/禁用JS脚本/滚动页面至元素/缩放页面

    版权声明:本文为博主原创文章,遵循CC4.0BY-SA版权协议,转载请附上原文出处链接和本声明。本文链接:https://blog.csdn.net/qqxx6661/article/details/97812782前言前几周做了个使用Selenium的项目,踩了好多好多好多的Selenium的坑,越来越感觉他作为一个第三方库,对于Chrome的操作实在是有局限。另外,推荐大家一个Selenium之外的操作浏览器的选择:puppeteer(https://github.com/GoogleChrome/puppeteer),是来自谷歌的库。它解决了很多在Selenium里很难解决的问题,比如手机页面截全屏。好了,收回来,Selenium很多难解决的问题,我们要首先想到从JS脚本出发,毕竟Selenium还是支持驱动浏览器运行JS脚本的。这篇文章的内容主要是Selenium日常开发中会遇到的坑,以Java代码为主,当然Python的小伙伴不用担心,这里所有的解决方案都是可以在Python中通用的。Selenium主要参考Selenium使用总结(Java版本):https://jueji

  • 告诉你一个真实的傅里叶

    “傅里叶”这个名字,相信很多人听到之后,一定都会觉得血液凝固、两腿发抖。。。在理工科大学生“恐惧”排行榜中,我相信傅爷一定稳居前三。 是的,没错,在我们最痛恨的灭绝级专业课中,“傅里叶”这三个字是出现频率最高的。傅里叶变换、傅里叶积分、傅里叶级数,傅里叶分析……每一个都会让你陷入极度的痛苦之中无法自拔。。。不过大家放心,今天这篇文章绝对不会让大家恐惧。小枣君要讲的,是傅爷一直不为人知的生平故事。我们还是从头开始吧。傅里叶(也有译作傅立叶),也就是我们的傅爷,全名是让·巴普蒂斯·约瑟夫·傅里叶(BaronJeanBaptisteJosephFourier),不好意思,容我喘口气。。。傅里叶 他是举世闻名的法国数学家,物理学家。 1768年3月21日,他生于法国中部奥塞尔的一个平民家庭,他的父亲是一个裁缝。他的童年并不算幸福,9岁时,双亲亡故,他变成一个孤儿,被当地的一个主教收养。1780年,他被教会送入镇上的军校就读,表现出对数学的特殊爱好。他还有志于参加炮兵或工程兵,但因家庭地位低贫而遭到拒绝。再后来,他希望到巴黎在更优越的环境下追求他有兴趣的研究,可是法国大革命中断了他的计划。无奈之

  • 死磕 java集合之TreeMap源码分析(二)- 内含红黑树分析全过程

    插入元素插入元素,如果元素在树中存在,则替换value;如果元素不存在,则插入到对应的位置,再平衡树。publicVput(Kkey,Vvalue){Entry<K,V>t=root;if(t==null){//如果没有根节点,直接插入到根节点compare(key,key);//type(andpossiblynull)checkroot=newEntry<>(key,value,null);size=1;modCount++;returnnull;}//key比较的结果intcmp;//用来寻找待插入节点的父节点Entry<K,V>parent;//根据是否有comparator使用不同的分支Comparator<?superK>cpr=comparator;if(cpr!=null){//如果使用的是comparator方式,key值可以为null,只要在comparator.compare()中允许即可//从根节点开始遍历寻找do{parent=t;cmp=cpr.compare(key,t.key);if(cmp<0)//

  • python项目练习四:新闻聚合

    书中的第四个练习,新闻聚合。现在很少见的一类应用,至少我从来没有用过,又叫做Usenet。这个程序的主要功能是用来从指定的来源(这里是Usenet新闻组)收集信息,然后讲这些信息保存到指定的目的文件中(这里使用了两种形式:纯文本和html文件)。这个程序的用处有些类似于现在的博客订阅工具或者叫RSS订阅器。先上代码,然后再来逐一分析:..code::pythonfromnntplibimportNNTP fromtimeimportstrftime,time,localtime fromemailimportmessage_from_string fromurllibimporturlopen importtextwrap importre day=24*60*60 defwrap(string,max=70): ''' ''' return'\n'.join(textwrap.wrap(string))+'\n' classNewsAgent: ''

  • 算法笔记--线性基求交模板

    https://blog.csdn.net/demon_rieman/article/details/88830846 模板1: structLinearBase{ LLv[32]; inlinevoidclr(){memset(v,0,sizeof(v));} inlinevoidins(LLa){ for(inti=31;i>=0;--i){ if(a&(1LL<<i)){ if(!v[i]){ v[i]=a; break; } a^=v[i]; } } } inlineboolcan_ex(LLa){ for(inti=31;i>=0;--i)if((a^v[i])<a)a^=v[i]; returna==0; } //交 inlinefriendLinearBaseoperator*(constLinearBase&a,constLinearBase&b){ LinearBaseall,c,d; all.clr(),c.clr(),d.clr(); for(inti=31;i>=0;--i){ all.v[i]=a.v

  • 应用处理http request不当导致的 TCP CLOSE-WAIT 大量堆积的问题

    应用处理httprequest不当导致的TCPCLOSE-WAIT大量堆积的问题 情况是这样:最近做过的一个安卓多渠道安装包在CDN场景下的差分打包、存储、分发的项目,这个项目在测试阶段,并没有暴露出什么问题,但是当上线到生产环境进行回归测试时,在第三方CDN回源到我们的源站这一层面的文件拉取上,暴露了一个严重问题,即:如果第三方CDN进行非Range的HTTPGET请求,如果客户端网速较慢,或者安装包过大,会导致无法成功下载到最后一片拥有META-INF的文件片,从而导致用户下载到的文件损坏。 排查故障过程: 去灰度环境下载一个已经成功发布了的安装包,安装包为600MB+,下载到590+MB时,速度掉到0,卡顿一段时间后提示下载失败。但是如果下载的是一个大小为十几兆的安装包,就没有问题。 第一反应是切片算法存在问题,立即用range跨分片请求,下载到的文件是没有问题的,可以用zipinfo读取到压缩信息,排除是切片算法的问题; 想到可能是pythonrequests函数中,指定的timeout过小,实际上,timeout分为两种,一个是connection_timeout

  • 空间直线同任意形状椭球交点

    空间直线同空间中三维椭球相交,其交点即为空间直线方程同椭球方程的解,对于空间直线方程,只要知道两点空间坐标即可,而欧拉角不为零的三维椭球方程则较难描述,但可以考虑对椭球进行变换,使其欧拉角为零,进而转化为标准椭球,标准椭球方程则容易描述,相应在对椭球进行变换的同时也许对空间直线进行相应的变换。由此,通过标准椭球方程同变换后的直线方程进行联立求解,即可获取交点坐标,下面简述求解过程及列出主要的计算公式。 约定本文采用右手系,空间旋转顺序为Z-Y-X。  6、示例  

  • Token Fund到底是什么?

         相比传统的VC基金,作为新生事物的TokenFund从一出场便吸引着行业目光的追随。行业早期ICO促使区块链行业野蛮生长,大量区块链项目涌现,同时也带动了大量“代投”朝TokenFund方向发展。那么什么是TokenFund?   其实关于TokenFund并没有一个特别准确的定义,一般而言,TokenFund并不特殊,被简单的认定为是进行token投资的基金。投资标的有所转变,从传统资本市场如股权、证券,转变为数字资产(股权、商品或者外汇);而交易过程也游走在各类交易场所、ICO平台、场外渠道、个人渠道等。   从TokenFund兴起的2017年上半年来算,入场的姿态有很多。一些投资人先用自己的钱试水,成立小型TokenFund,投一些项目,以获得认知和资源。在此基础上,再平行地去做股权投资。所以说,TokenFund1.0时代发生在2017年,随着数字资产的大热,TokenFund一度被誉为“躺着就能赚钱的机构”,甚至很多传统VC发展趋势也转向成立TokenFund,进行Token投资。   TokenFund的激励机制与VC不同,一个项目的运作同时涉及到一级市场的投资

  • toast组件小结

    简介:toast是“吐司”的意思,它属于android杂项组件,是一个简单的消息提示框,类似于javascript中的alert.  作用 显示文本 显示图片 显示图文   3.常用方法     show():显示消息提示框     makeText(Contextcontext,Charsquencetext,intduration):创建一个toast对象     setView(Viewview):该Toast显示的view组件   4.代码演示      MainActivity.class复制 publicclassMainActivityextendsAppCompatActivity{ @Override protectedvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstan

  • JMeter遇到的问题一:Error writing to server(转)

    Java.io.IOException:Errorwritingtoserver异常;我测试500个并发时,系统没有问题;可当我把线程数加到800时,就出现错误了,在“查看结果树”中,打开出错的请求,看到如下异常: java.io.IOException:Errorwritingtoserveratsun.reflect.GeneratedConstructorAccessor24.newInstance(UnknownSource)atsun.reflect.DelegatingConstructorAccessorImpl.newInstance(UnknownSource)atjava.lang.reflect.Constructor.newInstance(UnknownSource)atsun.Net.www.protocol.http.HttpURLConnection$6.run(UnknownSource)atjava.security.AccessController.doPrivileged(NativeMethod)atsun.net.www.protocol.h

  • 结果集存放到临时表

    在开发过程中,很多时候要把结果集存放到临时表中,常用的方法有两种。      1.INSERTINTOSELECT语句    语句形式为:InsertintoTable2(field1,field2,...)selectvalue1,value2,...fromTable1     要求目标表Table2必须存在,由于目标表Table2已经存在,所以我们除了插入源表Table1的字段外,还可以插入常量。       2.SELECTINTOFROM语句         语句形式为:SELECTvale1,value2intoTable2fromTable1         要求目标表Table2不存在,因为在插入时会自动创建表Table2,并将Table1中指定字段数据复制到Table2中。

  • sort排序

    #include<algorithm>voidsort(iteratorstart,iteratorend);voidsort(iteratorstart,iteratorend,StrictWeakOrderingcmp);第一个只需要传递你要排序的串(整形数组等都行)的头指针(数组第一个元素的指针)与数组最后元素的下一个位置,sort是一个模板哈第二个前面两个参数同第一,但第三个参数是传递一个你定义用于排序的函数(返回比较的大小值,如strcmp或自定义的都行),因为第一个用的是默认的哈复制 sort与stable_sort   复制 这两个函数的原理都是快速排序,时间复杂度在所有排序中最低,为O(nlog2n); sort的应用; 1、可以传入两个参数;    sort(a,a+N),其中a是数组,a+N表示对a[0]至a[N-1]的N个数进行排序(默认从小到大排序); 2、传入三个参数;    sort(a,a+N,cmp),第三个参数是一个函数;   &n

  • Codeforces1454D D. Number into Sequence

    D.NumberintoSequence timelimitpertest 3seconds memorylimitpertest 256megabytes input standardinput output standardoutput Youaregivenaninteger nn (n>1n>1). Yourtaskistofindasequenceofintegers a1,a2,…,aka1,a2,…,ak suchthat: each aiai isstrictlygreaterthan 11; a1⋅a2⋅…⋅ak=na1⋅a2⋅…⋅ak=n (i. e.theproductofthissequenceis nn); ai+1ai+1 isdivisibleby aiai foreach ii from 11 to k−1k−1; kk isthe 

  • 公众号自定义菜单加连接跳转显示“菜单跳转链接URL可能存在安全风险,请检查”怎么办?

    1.微信内打开该链接,申请恢复访问. 2.然后会提示违规的内容或链接,检查该链接是否有问题,然后申请恢复.  

  • 【.NET流操作】FileStream、NetWorkStream

    FileStream FileStream流继承于Stream类,代表一个文件流,使用FileStream类可以对文件进行读取、写入、打开和关闭操作 常用构造函数: publicFileStream(stringpath,FileModemode,FileAccessaccess); 复制 参数说明: path指明文件所在的路径信息; mode是FileMode的枚举值,表示文件打开或创建的方式,含义如下: CreateNew:指定操作系统应创建新文件,如果文件已经存在,则引发IOException; Create:指定操作系统应创建新文件,如果文件已经存在,它将被覆盖; Open:指定操作系统应打开现有文件,如果文件不存在,则引发FileNotFoundException; OpenOrCreate:指定操作系统应打开文件,如果文件不存在,则创建新文件; Truncate:指定操作系统应打开现有文件,文件一旦打开,就将截断为零字节大小; Append:打开先有文件并把Position设置至文件尾,如果文件不存在将创建新文件。Append只能同FileAccess.Write一起使用

相关推荐

推荐阅读