单例模式
什么是单例模式
有些时候某些对象我们只需要一个,比如说:线程池、缓存、对话框等等。事实上,这些对象只能有一个实例,如果制造出多个实例,就会导致许多问题产生。
为了保证对象只有一个实例,会想到全局变量,使用全局变量来保证单例时,就要在程序一开始就创建好对象。如果这个对象非常消耗资源,而程序在这次的执行过程中又没有用到他,会形成浪费。
虽然全局变量是可以实现单例的需求,但是仿佛有些不完美,单例模式可以完美的替代全局变量。
单例模式确保一个类只有一个实例,并提供一个全局访问点。
经典单例模式
public class Singleton {
private static Singleton instance;
private Singleton(){}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton ();
}
return instance;
}
}
多线程中的单例模式
在类加载的时候就创建单例实例对象:
public class SingletonA {
private static SingletonA instance = new SingletonA ();
private SingletonA(){}
public static SingletonA getInstance() {
return instance;
}
}
使用synchronized同步getInstance方法。但只有第一次执行此方法时,才真正需要同步。一旦设置好instance变量,就不再需要同步了,之后每次调用这个方法,同步都是一种累赘:
public class SingletonB {
private static SingletonB instance;
private SingletonB() {}
public static synchronized SingletonB getInstance() {
if (instance == null) {
instance = new SingletonB ();
}
return instance;
}
}
利用双重检查加锁:
public class SingletonC {
private volatile static SingletonC instance;
private SingletonC() {}
public static SingletonC getInstance() {
if (instance == null) {
synchronized (SingletonC.class) {
if (instance == null) {
instance = new SingletonC ();
}
}
}
return instance;
}
}
优点
单例模式会阻止其他对象实例化自己的单例对象副本,从而保证所有对象都访问唯一实例。
单例类控制了实例化过程,类可以灵活更改实例化过程。
缺点
由于单例模式中没有抽象层,因此单例类的扩展有很大的困难。
单例类不止提供全局访问,还在应用程序中担当角色,在一定程度上违背了单一职责原则。