简介:
单例模式时Java中最简单也最常用的的设计模式之一,它属于建造模式的一种,我们称使用了单例模式的类称为单例类,单例类需要负责创建自己的对象,同时确保只会生成一个实例,要注意不要被 GC 回收,也就是说,JVM 只存在该对象的一个实例。
单例模式的优点:
- 只会有一个实例存在,避免了反复创建销毁实例,降低内存使用率,减轻 GC 的压力。
- 避免对资源的多重占用
单例模式有两种:
- 懒汉式,懒汉式会延时加载对象,也就是说在需要的时候才创建实例。
- 饿汉式,饿汉式是即时加载的,在类加载时就会创建实例。
写单例模式要点:
- 创建一个静态变量,用来引用自身。
- 私用化构造方法,避免被外界调用,产生多个对象。
- 提供一个工厂方法,共外界获取该类实例。
- 要注意不要重复创建实例。
懒汉式
package singleton;
/**
* 懒汉式单例模式,延时加载,调用时才实例化自己
* 单例:一个 Jvm 中,该对象只有一个实例
* 缺点:多线程下不安全
* @author wqj24
*
*/
public class LazySingleton {
private static LazySingleton instance = null;
// 限制产生多个对象
private LazySingleton() {
}
// 静态工厂方法
public static LazySingleton getInstance() {
// 避免重复创建
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}
考虑多线程的的懒汉式
将创建对象的方法独立出来,并使用synchronized
关键字加锁
public class Singleton {
private static SingletonTest instance = null;
private SingletonTest() {
}
private static synchronized void syncInit() {
if (instance == null) {
instance = new SingletonTest();
}
}
public static SingletonTest getInstance() {
if (instance == null) {
syncInit();
}
return instance;
}
}
注意上面两个if
都有各自的作用,并没有冗余。
饿汉式
package singleton;
public class EagerSingleton {
// 私有化类变量,防止被引用,类被第一次加载时实例化(只实例化一次)
private static EagerSingleton instance = new EagerSingleton();
// 私有化构造方法
private EagerSingleton() {
}
// 静态工厂方法
public static EagerSingleton getInstance() {
return instance;
}
}
测试:
package singleton;
import org.junit.Test;
public class TestMain {
// 懒汉单例模式测试
@Test
public void lazyTest() {
LazySingleton s1 = LazySingleton.getInstance();
LazySingleton s2 = LazySingleton.getInstance();
System.out.println(s1 == s2);
}
// 恶汉单例模式测试
@Test
public void eagerTest() {
EagerSingleton s1 = EagerSingleton.getInstance();
EagerSingleton s2 = EagerSingleton.getInstance();
System.out.println(s1 == s2);
}
}
结果都是 true。