单例模式的特点:
1、单例类只能有一个实例
2、单例类必须自己创建自己的唯一实例
3、单例类必须给其他对象提供这一实例
单例模式又分为懒汉式单例模式和饿汉式单例模式
1.懒汉式单例模式(顾名思义,很懒,在类加载时,不创建实例,因此类加载速度快,但运行时获取对象速度慢)
1.1.线程不安全的懒汉式单例模式
1.2.线程安全的懒汉式单例模式(加synchronized 关键字)
2.饿汉式单例模式(执行效率比较高,但是在类加载时就实例化,比较浪费内存)
1、普通懒汉式(线程不安全)
public class Singleton{
// 静态私有化成员,没有初始化
private static Singleton singleton = null;
// 私有化构造方法,阻止外部直接实例化对象
private Singleton(){}
// 获取类的单例实例
public static Singleton getInstance(){
if(singleton == null){
singleton = new Singleton();
}
// 返回类的唯一实例
return singleton;
}
}
这是懒汉式中最简单的一种写法,只有在方法第一次被访问时才会实例化,达到了懒加载的效果。但是这种写法有个致命的问题,就是多线程的安全问题。假设对象还没被实例化,然后有两个线程同时访问,那么就可能出现多次实例化的结果,所以这种写法不可采用。
2、同步方法懒汉式(线程安全)
public class Singleton{
// 静态私有化成员,没有初始化
private static Singleton singleton = null;
// 私有化构造方法,阻止外部直接实例化对象
private Singleton(){}
// 获取类的单例实例
public static synchronized Singleton getInstance(){
if(singleton == null){
singleton = new Singleton();
}
// 返回类的唯一实例
return singleton;
}
}
这种写法是对getInstance()加了锁的处理,保证了同一时刻只能有一个线程访问并获得实例,但是缺点也很明显,因为synchronized是修饰整个方法,每个线程访问都要进行同步,而其实这个方法只执行一次实例化代码就够了,每次都同步方法显然效率低下。
3、饿汉式
public class Singleton{
private static Singleton singleton = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return singleton;
}
}
这是比较常见的写法,在类加载的时候就完成了实例化,避免了多线程的同步问题。当然缺点也是有的,因为类加载时就实例化了,如果该实例没被使用,内存就浪费了。
单例模式优缺点:
优点:单例类只有一个实例,节约内存,可以提高系统的性能。
缺点:单例模式一般没有接口,需要扩展的话除了修改代码基本上没有其他途径。