单例模式
单例模式,是我们在初学java时便接触过的一个相对简单的设计模式,也是应用最广泛的一个模式,在经历了一年编程学习的今天,写项目时偶然用到单例模式,有了一些新的理解,写出来与大家分享,下面先简单的介绍一下单例模式。
单例模式(Singleton Pattern)在网上摘抄了一段关于他的官方定义,就是确保某一类只有一个实例,而且自行实例化并向整个系统提供这个实例。下面我们用一张通用的类图来展示一下单例模式的设计:
SinglePattern类称为单例类,通过使用private修饰构造函数,以确保该类在外部不可以通过new关键字实例化,并且在类中使用自己的new SinglePattern来自行实例化,通用代码如下:
public class SingletonPattern{ //限制产生多个对象 private SingletonPattern(){} private static SingletonPattern singleton = new SingletonPattern(); //通过该方法获得实例 public SingletonPattern getSingleton(){ return singleton; } //注:在类中的其他方法尽量使用静态方法 }
我们在上面提到过单例模式是一个应用非常广泛的设计模式,那么我们来看看他对于程序有什么优点呢?
1.一般单例模式在内存中只有一个实例,减少了内存的使用,当有一个对象需要频繁的创建和销毁时,使用单例模式就有很大的优势。
2.单例模式可以避免对资源的多重占用,列如一个写文件的动作,由于只有一个实例存在内存中,避免对同一资源文件的同时操作。
3.单例模式可以在系统设置全局的访问点,优化和共享资源访问,例如可以设计一个单例类,负责所有数据表的映射处理。
这样公式化的说可能大家很难理解,就用一个我真实做项目时的例子类给大家说明,那是一个C#的winform窗体程序,要做的是从所有磁盘中搜索MP3后缀的文件并列出,再点击歌曲名称时弹出微软自带WMP播放器播放,这时候就出现了一个问题,就是在打开一首歌曲后不关闭该播放器,当再点击下一首歌曲时会再度弹出一个新的播放器窗口,造成了一个两首歌同时播放的效果。
那么这个问题该如何解决呢?这就用到了我们今天说的单例模式,也就是把窗体套用到上面的通用代码中,这样一试,哎!问题解决了,可是在接下来的测试中,又发现了一个新的问题,那就是当前歌曲播放时,我们再度点击该歌曲,虽然不会再弹出新的播放窗口了,可是播放的歌曲进度却是变成了重新开始。我们知道,我们一般用的播放器软件,当点击当前播放歌曲时,都是会现实歌曲进度,不会重新播放的,那么这个问题怎么解决呢?我记得当时面对这个问题时可是十分的困扰,可谓愁白了少年头,后来在度娘以及一系列大神的博客的帮助下找到了解决问题的办法,也就是修改了一下单例模式方法中的代码,算是一个小小的扩展:
public partial class XPlayer : Form { private XPlayer() { InitializeComponent(); } //把用来自行实例化的静态变量改为不是常量,并且为空 private static XPlayer play = null; public XPlayer GetXPlayer() { //在创建对象的时候,先判断对象是否为空,为空创建,不为空让他等于自身 if (play == null) { play = new XPlayer(); } else { play = play; } return play; } }
这就是改变后的方法,可是该方法有一个明显的缺陷就是线程不安全,如一个线程A执行到 play = new XPlayer(),但还没获得对象(对象初始化需要时间),第二个线程B也在执行,执行到 if (play == null) 判断,那么线程B获得的判断条件也是真,这样程序就会出现两个对象,所以该方法只适合在低并发的时候使用,在并发量增加时应该考虑换更优方案或加判定。
单例模式还有一种扩展叫做有上限的多例模式,这种模式限定了到底能实例化出几个新的对象,因为在实际中应用较少,所以在这就不细说了,大家如果有更好的对于单例模式的用法和看法请多多提出。