设计模式有很多种,相信大家用的最多的应该是单例设计模式,也是应用最为广泛的设计模式。下面将带领大家来学习下。
Singleton是一种创建型模式,指某个类采用Singleton模式,则在这个类被创建后,只可能产生一个实例供外部访问,并且提供一个全局的访问点。
一个单例模式的核心是什么?
- 将采用单例设计模式的类的构造方法私有化(采用private修饰)。
- 在其内部产生该类的实例化对象,并将其封装成private static类型。
- 定义一个静态方法返回该类的实例。
必须满足上面三点才能称作单例设计模式。下面代码实现下
1,饿汉式
代码如下:
public class Singleton {
// 定义一个私有的构造方法
private Singleton() {
}
// 将自身的实例对象设置为一个属性,并加上static和final修饰符
private static final Singleton mInstance = new Singleton();
// 静态方法返回该类的实例
public static Singleton getInstance() {
return mInstance;
}
}
优点:写起来比较简单,而且不存在多线程同步问题,避免了synchronized所造成的性能问题
缺点:当类Singleton被加载的时候,会初始化static的mInstance,静态变量被创建并分配内存空间,从这以后,这个static的mInstance对象便一直占着这段内存(即便你还没有用到这个实例),当类被卸载时,静态变量被摧毁,并释放所占有的内存,因此在某些特定条件下会耗费内存。
2,饱汉式(线程不安全)
代码如下:
public class Singleton {
//定义一个内部实例化对象
private static final Singleton mInstance;
//定义私有构造
private Singleton() {
}
//定义一个静态方法,用于获取实例,这里会有线程安全性问题
public static Singleton getInstance () {
if(mInstance == null) {
mInstance = new Singleton();
}
return mInstance;
}
}
优点:写起来比较简单,当类Singleton被加载的时候,静态变量static的mInstance未被创建并分配内存空间,当getInstance方法第一次被调用时,初始化instance变量,并分配内存,因此在某些特定条件下会节约了内存;
缺点:多线程环境下很可能出现多个Singleton实例。
3,饱汉式(线程安全一)
代码如下:
public class Singleton {
//定义一个内部实例化对象
private static final Singleton mInstance;
//定义私有构造
private Singleton() {
}
//定义一个静态方法,用于获取实例,使用synchronized 避免多线程访问时,可能造成重的复初始化问题,性能有点低
public static synchronized Singleton getInstance () {
if(mInstance == null) {
mInstance = new Singleton();
}
return mInstance;
}
}
优点:使用synchronized关键字避免多线程访问时,出现多个Singleton实例。
缺点:频繁访问的时候由于同步问题,导致性能比较低
4,饱汉式(线程安全二)
代码如下:
public class Singleton {
//定义一个内部实例化对象
private static final Singleton mInstance;
//定义私有构造
private Singleton() {
}
//定义一个静态私有变量(不初始化,不使用final关键字,使用volatile保证了多线程访问时mInstance变量的可见性,避免了mInstance初始化时其他变量属性还没赋值完时,被另外线程调用)
public static volatile Singleton getInstance () {
if(mInstance == null) {
synchronized(Singleton.this) {
if(mInstance == null) {
mInstance = new Singleton();
}
}
}
return mInstance;
}
}
注意:该方法是多线程情况下最佳的实现单例的方案