第一次使用markdown来写博客。
单例设计是为了保证一个类仅有一个实例。在保证了一个类只有一个实例之后,要再对外界提供一个全局访问实例的方法。在java中,保证类只有一个实例,通过构造方法私有化防止外部进行实例化;全局访问点通过类的静态方法返回类的实例。
-
使用单例的好处:
- 保证一个类只有一个实例,减少对象,节省内存
- 方便对对象的控制
什么时候用:
设计模式真正难点在使用场景上,即什么时候用,很多时候一些模式其实你都知道了,但是你就是没用上,就是什么呢时候用这点还没有弄清。
相对来说,单例设计模式是比较容易理解的,也是比较常用的。但是在什么时候用也是比较难以说明的。简单来说,当你只需要一个类的实例的时候使用单例,一般在使用工具类。
#####如何实现:
单例模式另一个比较难一点的可能就是实现了。
- 贪婪模式
单例的实现方式有两种一种是贪婪模式。
贪婪模式指的是在类加载的时候就进行实例化,
这种方式比较适合在
1)确认对象一定会被使用
2)并且对象不是很大的时候
在2)我的理解:如果对象很大,但要去获取的资源不多,那么比较适合使用非贪婪模式即懒加载的方式;反之如果对象很大,并且实例化的时候要去获取很多资源来进行实例化,那么其实越早实例化越好,在类加载的时候花5秒总比用户用的时候花5秒好得多。
贪婪模式有两种实现方法:
- 直接使用枚举,有点类似 public static SingleInstance instance ,但是还是有一定差别的。
- 枚举的方式比公有方式访问符合设计
- 枚举的方式比较简洁,例如,如果实例化不用到其他的资源,连构造方法私有化都不用写
- 反射和系列化的问题也解决了(effective java),单例对象如果进行系列化和反系列化之后的对象,与原对象可能不是同一个对象。这个不详说,这方面有兴趣看effective
- 直接就实例化并且访问方式为私有,提供getInstance的时候直接返回对象
贪婪模式的好处: 不用去考虑线程问题导致的初始化实例超过一个
- 非贪婪(懒加载)模式
如果对象不确定一定会被使用,则更适合使用非贪婪模式,在全局访问点getInstance的时候进行初始化。
这时要考虑线程问题。
一种粗劣的方法是在,整个getInstance方法上或者整个方法体上进行锁定,这种的缺点是减慢整个方法的速度。
另一种方法是在实例化的时候,因为要防止的只是多次实例化。
流程:
假设有两条线程都判断了singleInstance为空,然后就进入了锁定的实例化代码;其中一个先进入了并进行实例化了,这时轮到到另一条线程执行实例化,为了防止重复实例化,因此需要再进行一次判断singleInstance是否为空,
public static SingleInstance getInstance() {
if (singleInstance == null) {
synchronized (SingleInstance.class) {
if(singleInstance==null){
singleInstance = new SingleInstance();
}
}
}
return singleInstance;
}
单例模式在设计模式中是比较容易理解的一种模式
多说一个:
类上的单例模式,类本身只有一个,因此如果不是考虑到本地方法栈大小,并且该类不需要与其他对象关联的 (方法需要的变量可以简单通过少量参数提供),可以直接使用类单例,即类上定义静态方法即可,不需要进行实例化的对象