谈谈单例模式
设计模式分为三类:创建型、结构性、行为型。
今天就谈一下创建型中的单例模式,什么觉创建型?创建型简单的来说就是关注于类的创建。
下面直接开始撸代码
创建一个控制台程序,建一个Singleton类
这里我们建了一个构造函数,假设他很费时间,构造一次就打印一次消息
运行,我们看看结果
可以看到,每实例化一次,就会打印一次,那是不是很浪费资源,这个时候单例模式就可以解决这个问题了,我们改造一下代码
好,这个就改造好了,我们看一下结果
这里可以看到,我们调用五次,实际上他只实例化一次,这就是单例模式了,好像是没毛病了,但是有一个情况没有考虑到,那就是线程。我们现在是单线程的,当然没问题了,多线程的情况下,我们这个代码能正常嘛,我们试一下。
结果显而易见,被构造了五次,那怎么办呢,办法还是有的,加锁,现在网上搜一堆都能看到加锁
为了形象一点,我们再写一个show方法来调一下
看下结果
ok,完美解决,但是仔细想想,调用五次,每个线程都要在锁那里等待完成,那不是不管这个Singleton有没有被实例化,只有要我调用,那一定就会等待,那怎么办呢,这个时候有个办法就可以解决,双重判断,记得我第一次上网搜索单例模式的时候看到这个完全懵逼,不知道是怎么是做什么的
好,现在来假设一下,当我第一次进来的时候,没有被实例化,五个红色的都能进入第一个判断,然后等待第一个完成这一系列操作,然后我在调一次,这次是五个蓝色的,第一层判断的时候就到头了,因为前面的那次调用已经实例化一次了,所以这里减少了等待的时间,直接从内存中读取,提升性能。
这种模式被称为懒汉模式,还有一种叫饿汉模式
比如这个,一个静态的构造函数,会在实例化Singleton之前由CLR调用一次,而且只会调用一次。所以就不存在多线程的困扰。
只要你调用提供给外界的方法,就直接返回Singleton。这里说一下,静态字段要比静态方法先执行,看代码就能看出来,我是先定义,后赋值的。结果就截图了,这种简单的例子脑海中转一下就OK了;
总结:单例模式保证在进程中唯一,也就是说当进程启动,永远不会释放内存,知道进程停止,所以千万不要有想法每个类都来个单例模式,毕竟设计模式这种高大上的东西对吧。单例模式要在特定的环境下使用,能不用就不用,比如数据库的连接池,缓存等等这些这些可以使用。