单例模式介绍
单例模式,是为了确保在整个软件体统中,某个类对象只有一个实例,并且该类通常会提供一个对外获取该实例的public方法(静态方法)。
比如日志、数据库连接池等对象,通常需要且只需要一个实例对象,这就会使用单例模式。
单例模式的八种模式
- 饿汉式(静态常量)
- 饿汉式(静态代码块)
- 懒汉式(线程不安全)
- 懒汉式(同步方法)
- 懒汉式(同步代码块)
- 懒汉式(双重检查)
- 静态内部类
- 枚举
下面依次来说明一下:
饿汉式(静态常量)
通常,我们创建一个对象的方式就是new,但是,当我们考虑只创建一个实例的时候,就应该禁止外部来通过new的方式进行创建。同时,由于无法使用new,你应该考虑提供一个获取单例对象的方式给别人。
思路
1.将构造器私有化(防止外部new,但是对反射还是有局限)
2.类的内部创建对象
3.对外提供一个获取实例静态的public方法
代码实现如下:
public class Singleton1 {
public static void main(String[] args) {
HungrySingleton hungrySingleton = HungrySingleton.getInstance();
HungrySingleton hungrySingleton1 = HungrySingleton.getInstance();
System.out.println(hungrySingleton == hungrySingleton1);
}
}
class HungrySingleton {
//1.私有化构造器
private HungrySingleton() {
}
// 2.类内部创建对象,因为步骤3是static的,
// 该方法也是static的
private static HungrySingleton instance = new HungrySingleton();
//3.对外提供一个获取对象的方法,
// 因为调用方式的目的就是为了获取对象,
// 所以该方法应该是static的。
public static HungrySingleton getInstance() {
return instance;
}
}
运行程序显示,我们的确只创建了一个对象实例。
小结
优点:代码实现比较简单,在类加载的时候就完成了实例化,同时,该方式能够避免线程安全问题。
缺点:在类装载的时候就完成实例化,没有达到Lazy Loading的效果。如果从始至终从未使用过这个实例,则会造成内存的浪费。
这种方式基于classloder机制避免了多线程的同步问题,不过, instance在类装载时就实例化,在单例模式中大多数都是调用getInstance方法, 但是导致类装载的原因有很多种, 因此不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化instance就没有达到lazy loading的效果。