单例模式(Singleton),是一种常用的软件设计模式。在应用这个模式时,单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。
一个类能返回对象一个引用(永远是同一个)和一个获得该实例的方法(必须是静态方法,通常使用getInstance这个名称);当我们调用这个方法时,如果类持有的引用不为空就返回这个引用,如果类保持的引用为空就创建该类的实例并将实例的引用赋予该类保持的引用;同时我们还将该类的构造函数定义为私有方法,这样其他处的代码就无法通过调用该类的构造函数来实例化该类的对象,只有通过该类提供的静态方法来得到该类的唯一实例。
单利模式适用场景:
单例模式只允许创建一个对象,因此节省内存,加快对象访问速度,因此对象需要被公用的场合适合使用,如多个模块使用同一个数据源连接对象等等。如:
1、需要频繁实例化然后销毁的对象。
2、创建对象时耗时过多或者耗资源过多,但又经常用到的对象。
3、有状态的工具类对象。
4、频繁访问数据库或文件的对象。
实现单利模式的原则和过程:
1、单例模式:确保一个类只有一个实例,自行实例化并向系统提供这个实例
2、单例模式分类:懒汉式(调用取得实例的方法如getInstance时才会实例化对象),饿汉式(类加载时实例化一个对象给自己的引用),双重校验锁的形式,静态内部类的形式,枚举类的形式。(java中饿单例模式性能优于懒单例模式,c++中一般使用懒单例模式)
3、单例模式要素: a.私有构造方法 b.私有静态引用指向自己实例 c.以自己实例为返回值的公有静态方法
1、懒汉式:单例实例在第一次被使用时构建,延迟初始化。
public class Singleton {
private static Singleton singleton;
private Singleton() {
}
public static Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
优点: 避免了饿汉式的那种在没有用到的情况下创建事例,资源利用率高,不执行getInstance()就不会被实例,可以执行该类的其他静态方法。
缺点: 懒汉式在单个线程中没有问题,但多个线程同事访问的时候就可能同时创建多个实例,而且这多个实例不是同一个对象,虽然后面创建的实例会覆盖先创建的实例,但是还是会存在拿到不同对象的情况。解决这个问题的办法就是加锁synchonized,第一次加载时不够快,多线程使用不必要的同步开销大。
2、饿汉式:单例实例在类装载时就构建,急切初始化。(预先加载法)
public classSingleton {
private static Singleton singleton=new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return singleton;
}
}
优点: a.线程安全 b.在类加载的同时已经创建好一个静态对象,调用时反应速度快。
缺点: 资源效率不高,可能getInstance()永远不会执行到,但执行该类的其他静态方法或者加载了该类(class.forName),那么这个实例仍然初始化。
3、双重校验锁
public class Singleton {
private volatile static Singleton singleton;
private Singleton() {
}
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
关键字volatile,用来解决多处理器变量共享的问题。
优点: 资源利用率高,不执行getInstance()就不被实例,可以执行该类其他静态方法。
缺点: 第一次加载时反应不快,由于java内存模型一些原因偶尔失败。